s e o p p o r t . l o g

Today I Learned

2024.02.02 TIL

Seo Ji Won 2024. 2. 5. 19:55

prop-drilling 코드 Context API로 리팩토링 하기

프로젝트의 컴포넌트와 props 구조

 

작업중인 팬 레터 사이트 프로젝트의 컴포넌트와 전달받는 props들을 도식으로 정리해보았다.

프로젝트 구조를 살펴보면 Home과 Detail 페이지에서는 단순히 프롭스를 받아서 하위 컴포넌트로 전달하는 역할만을 수행하고 있다.

이를 해결하기 위해 context를 통해 state를 전역에서 관리하도록 수정하였다.

최상위 컴포넌트인 router.js 에서 편지를 저장하는 state를 정의하였고,

<BrowserRouter>
      <LetterContext.Provider
        value={{
          savedLetters,
          setSavedLetters,
        }}
      >
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="details/:id" element={<LetterDetailPage />} />
        </Routes>
      </LetterContext.Provider>
    </BrowserRouter>

 

선택 캐릭터 정보는 Home컴포넌트에서만 쓰이기 때문에 Home 컴포넌트에서 정의하여 context로 관리하였다.

<CharacterContext.Provider value={{
            selectedCharacter,
            setSelectedCharacter
        }}>
            <LetterSendingBox />
            <LetterBoxSelector />
            <LetterSummaryView />
</CharacterContext.Provider>

 

context로 관리한 프로젝트 구조

 

트러블 슈팅 -  초기 렌더링 시 undefined 오류 및 useEffect로 발생하는 렌더링 문제

문제 상황

페이지가 불러와지면 한 번 렌더링이 발생하고, useEffect 내부의 setSavedLetters로 인해 또 다른 렌더링이 발생하는 문제 발생 또한 useEffect 실행 후에만 context 값이 정의되기 때문에, 초기 렌더링 시 undefined 오류가 발생

  useEffect(() => {
    const loadData = async () => {
      try {
        const res = await fetch("http://localhost:4000/data");
        const data = await res.json();
        setSavedLetters(data);
      } catch (error) {
        console.log(error);
      }
    };
    loadData();
  }, []);

 

오류 내역

Cannot read properties of undefined (reading '_context')

원인 분석

  1. useEffect 내부에서 setState로 상태를 업데이트하고 있어서 렌더링이 다시 발생한다.
  2. 초기 렌더링 시에 context의 값이 undefined이므로 해당 값에 접근 시 오류가 발생한다.

context를 콘솔에 찍어본 내역

 

콘솔에 찍힌 내역을 보면 브라우저 구동 후 일단 한번 렌더링이 되고있고, 이 때 context에서 받아온 값은 비어있다.

useEffect로 값을 받아온 후에는 정상적으로 데이터가 들어있는 것을 알 수 있다.

이로 인해 초기 렌더링시 데이터를 뿌려주는 과정에서 undefined 이슈로 에러가 발생하였다.

 

문제 해결

일단 useContext로 Context만 먼저 불러오고, useEffect 실행 후에 context에서 value값을 뽑아오도록 하니까 해결되었다.

const data = useContext(LetterContext.savedLetters)
    console.log(data)

이렇게 하면 undefined 오류나고

    const data = useContext(LetterContext)
    console.log(data.savedLetters)

이렇게 하면 잘 불러와진다.. (왜 이렇게 하면 오류가 안 나는지 확실하게는 모르겠다..;;)

 

useEffect로 값을 불러오면서 set을 하지말고, 변수에 담아서 return하고 그 변수를 넘겨주도록 시도해봤는데 잘 안됐다.

letterContext의 savedLetters의 길이가 0 이상일때만 작업을 수행하도록 할수도 있겠다.

근본적인 해결은 아니여서 필수요구사항 완료 후 다시 리팩토링이 필요하다.

 

 

'Today I Learned' 카테고리의 다른 글

2024.02.06 TIL  (0) 2024.02.06
2024.02.05 TIL  (0) 2024.02.05
2024.02.01 TIL  (0) 2024.02.01
2024.01.31 TIL  (0) 2024.01.31
2024.01.30 TIL  (0) 2024.01.30