정의, 형태
const value = useContext(context)
cocontext 객체(React.createContext에서 반환된 값)을 받아 그 context의 현재 값을 반환한다. context의 현재 값은 트리 안에서 이 Hook을 호출하는 컴포넌트에 가장 가까이에 있는 <MyContext.Provider>의 value prop에 의해 결정된다. - 공식문서
컴포넌트에서 가장 가까운 <MyContext.Provider> 가 갱신되면 이 Hook은 그 provider에게 전달된 가장 최신의 context value를 사용하여 렌더러를 트리거한다. 상위 컴포넌트에서 React.memo 또는 shouldComponentUpdate를 사용하더라도 useContext를 사용하고 있는 컴포넌트 자체에서부터 다시 렌더링된다.
useContext를 호출한 컴포넌트는 context 값이 변경되면 항상 리렌더링된다. 즉, useContext로 구독을 한다고 보면 된다.
활용
// 부모 컴포넌트
<MyContext.provider value={내려줄 것들}>
// ...자식들
</MyContext.provider>
// 자식 컴포넌트
//...생략
const { 가져오고 싶은 애들} = useContext(MyContext)
// 자유롭게 사용하면 된다.
현 프로젝트에서 이미지 편집기를 개발 중인데 prop을 너무 자식들을 3중 4중으로 내려줘야 하는 경우가 많았다. 그래서 useContext를 활용해서 자유롭게 쓸 수 있게 했다.
하지만 해당 context의 값이 변경될 때마다 리렌더링이 되기 때문에 성능적인 부분에서 이슈가 있을 수 있다. 지금 프로젝트의 경우 편집기에서 1개의 context에 모든 필요한 변수,함수들을 묶어놓았는데, 이는 성능에 많이 안 좋다. 추후에 각 기능별로 묶어서 여러개의 context를 사용하는 방향으로 리팩토링할 것이다
최적화
상태의 getter, setter를 다른 context에 분리하여 담아준다. 상태 setter는 변하지 않기 때문이다.
그다음 각 gettter와 setter를 useMemo
를 활용해서 메모이제이션해줌으로써 불필요한 재랜더링을 막을 수 있다.
export const EditorProvider = ({ children }: { children: ReactNode }) => {
const [cells, setCells] = useState<ICell[][]>(getDefaultCells(defaultCellCol, defaultCellRow))
const values = useMemo(
() => ({
cells,
}),
[cells]
)
const actions = useMemo(
() => ({
setCells,
}),
[]
)
return (
<EditorActionsContext.Provider value={actions}>
<EditorValuesContext.Provider value={values}>{children}</EditorValuesContext.Provider>
</EditorActionsContext.Provider>
)
}
에러처리
context provider 내부가 아닌 다른곳에서 해당 context를 useContext
해서 쓰면 에러가 아니라 값이 undefined로 보여진다.
따라서 해당 부분을 커스텀훅으로 분리해서 value가 undefined
인 경우 에러를 던지도록 처리할 수 있다.
export function useEditorValues() {
const value = useContext(EditorValuesContext)
if (value === undefined) {
throw new Error('useEditorValues should be used within EditorProvider')
}
return value
}
'프론트엔드 > React' 카테고리의 다른 글
HOC (1) | 2022.06.04 |
---|---|
useCallback 과 useMemo (0) | 2022.06.04 |
Memoization (0) | 2022.06.04 |
useReducer (0) | 2022.05.14 |
재조정 (Reconciliation) (0) | 2022.03.11 |