본문 바로가기
source-code/React

Cannot read properties of null (reading 'useContext') 에러 해결

by mattew4483 2024. 1. 16.
728x90
반응형

배경

사내 서비스에서 공통으로 사용하는 모듈들을 위한 패키지를 개발하는 도중, 위 에러와 마주쳤습니다.

문제가 된 상황은 다음과 같았습니다.

1. A 패키지는 B, C 프로젝트에서 공통으로 사용하는 모듈들을 제공합니다.
2. 이때 공통으로 사용되는 모듈들에는, 기본 css가 적용된 styled-components가 포함됩니다.
3. B 프로젝트는 A 패키지가 제공하는 styled-components 컴포넌트를 사용합니다.
4. B 프로젝트는 위 컴포넌트뿐만 아니라, 서비스 내 스타일링을 위해 자체적으로 styled-components를 사용합니다.

문제 상황

개발 환경에서는 아무런 문제도 발생하지 않았습니다.

 

A 패키지에서 styled-components를 사용한 react component(편의상 StyledComponent)를 exports 하고,

B 패키지에서는 A 패키지를 설치한 후 StyledComponent를 사용한 후,

B 패키지 내부적으로 styled-component를 통해 다른 react component를 사용한 뒤,

B 패키지를 번들링 해 런타임에 실행했습니다.

// A package
import {styled} from 'styled-components'
export const StyledComponent = styled.div`
	// css styling
`

// B project
import {StyledComponent} from 'A package'
import {styled} from 'styled-components'

const AnotherStyledComponent = styled.div`
	// css styling
`

const App = () => {
	return(
            <>
                <StyledComponent/>
                <AnotherStyledComponent/>
            </>
           )
}

컴파일 시점에는 아무런 문제가 없어 보입니다.

띠용

하지만, B 프로젝트를 번들링 해 런타임에서 실행한 결과...

콘솔에 Cannot read properties of null (reading 'useContext') 에러가 발생했습니다.

A, B 패키지 내에 useContext는 사용조차 되지 않았는데 말이죠. 어떻게 된 일일까요?

원인 분석

우선 위 에러 문구에 대해 검색을 시작했습니다.

https://stackoverflow.com/questions/72413194/uncaught-typeerror-cannot-read-properties-of-null-reading-usecontext

 

Uncaught TypeError: Cannot read properties of null (reading 'useContext')

so no where in my react code do I use the useContext property. I have a npm package which has a compiled webpack file that has a component in there. when i try to use the component in my react app it

stackoverflow.com

https://stackoverflow.com/questions/74322410/how-to-fix-cannot-read-properties-of-null-reading-usecontext

 

How to fix cannot read properties of null (reading 'useContext')?

I can't find where the culprit is. I tried to debug it, but can't found what really make it those error: cannot read properties of null (reading 'useContext') && react.development.js:209

stackoverflow.com

일반적으로 react에서 위 에러가 발생했을 때의 원인으로는

1) 패키지 간 호환되지 않는 버전 의존

2) 여러 버전의 패키지 중복 설치 등이 있었습니다.

 

이에 대한 해결책으로 → package.json에 peer dependency를 추가하거나, node modules를 재설치하라고 하지만...

이 역시 정상적으로 동작하지 않았습니다.

어찌 된 영문일까

무엇이 문제일지 고민하며 이런저런 테스트를 해 본 결과...

위 에러는 B 프로젝트에서 A 패키지의 StyledComponent를 호출했을 때만 발생함을 확인할 수 있었습니다!

 

A 패키지가 제공하는 다른 모듈들이나, styled-component를 사용하지 않은 react component를 사용했을 때는 발생하지 않았죠.

→ styled-component 라이브러리와 관련된 문제임을 짐작할 수 있었습니다.

 

위 두 사례를 종합하고 나니,

혹시 styled-component 라이브러리가 B 프로젝트를 번들링 할 때, 중복으로 설치되는 건 아닐까? 하는 생각이 들었고

https://memostack.tistory.com/318

 

Rollup 모듈에서 Cannot read properties of null (reading 'useState') 오류 조치

오류 내용 rollup으로 공통으로 사용할 ui 모듈을 생성하여, web app에 가져다가 사용하는 도중에 아래와 같은 오류가 발생했다. Uncaught TypeError: Cannot read properties of null (reading 'useState') 오류 내용은 nu

memostack.tistory.com

관련된 키워드로 검색을 하다 보니... Rollup 번들러에서 유사한 문제를 겪은 케이스를 찾을 수 있었습니다!

해결 방안

위 사례 역시 동일한 문제를 겪고 있었습니다.

1) styled-component로 생성한 react-component를 제공하는 패키지 개발

2) 패키지 설치 및 styled component 사용

3) 해당 프로젝트에서 styled-component 설치 및 사용

4) 번들링 및 실행 → 에러 발생! 

 

즉 정확한 이유는 알 수 없지만, 

A 패키지에서 번들링 한 styled component를

B 프로젝트에서 다시 번들링 해 사용하는 경우

Cannot read properties of null (hooks) 에러가 발생하는 것이죠.

 

아하... 이 경우 해결책은 간단합니다.

A 패키지를 번들링 할 때, styled-component를 번들에 포함하지 않고, 외부에서 로드하게끔 만들면 되겠습니다.

const esbuild = require('esbuild');

esbuild.build({
  entryPoints: ['entry.js'],
  bundle: true,
  outfile: 'output.js',
  external: ['styled-components'],
}).catch(() => process.exit(1));

저는 esbuild를 사용하고 있었기 때문에, external 옵션을 통해 styled-component 라이브러리를 번들에서 제거했습니다.

 

그리고 이 경우 해당 패키지를 사용하는 쪽(외부)에서

styled-components 라이브러리를 구현 후 로드해야 하므로...

// A package
// package.json
{
  "peerDependencies": {
    "styled-components": "^6.1.1"
  }
}

A package에서 peerDependencies 옵션을 통해, 해당 조건을 명시해 줬습니다.

728x90
반응형