eslint 설정을 진행하던 도중 ,
전역 context를 사용하던 모든 부분에서 아래와 같은 에러가 발생했다
The object passed as the value prop to the Context provider (at line 9) changes every render. To fix this consider wrapping it in a useMemo hook.
이 에러는 React Context API에서 제공하는 Provider 컴포넌트에 전달되는 value prop이 매 렌더링마다 변경되는 경우에 발생한다고 한다
그냥 ESLint 옵션 자체를 off나 warn으로 해버려도 된다
그렇지만 메모이제이션 자체가 긍정적인 효과를 가져다 주기도 하며 , 무작정 옵션을 끄는 것을 지양하고자 메모이제이션을 진행해보기로 했다
useMemo 훅을 사용하여 Provider에 전달되는 객체를 메모이제이션 해 보았다
LoginContext.tsx
import React, { createContext, useState, useContext, useMemo } from 'react';
import { LoginContextValue } from '../../types/context';
export const LoginContext = createContext<LoginContextValue | null>(null);
export const LoginProvider = ({ children }: { children: React.ReactNode }) => {
const [isLoggedIn, setIsLoggedIn] = useState(false);
// useMemo 사용
const memoValue = useMemo(() => {
return { isLoggedIn, setIsLoggedIn };
}, [isLoggedIn]);
return <LoginContext.Provider value={memoValue}>{children}</LoginContext.Provider>;
};
export function useLoginAPI() {
return useContext(LoginContext);
}
ModalContext.tsx
import React, { createContext, useContext, useMemo, useState } from 'react';
import { ModalContextValue } from '../../types/context';
export const ModalContext = createContext<ModalContextValue | null>(null);
export const ModalProvider = ({ children }: { children: React.ReactNode }) => {
const [isModalOpen, setIsModalOpen] = useState(false);
const [modalContents, setModalContents] = useState((<></>) as React.ReactNode);
const openModal = (children: React.ReactNode) => {
setIsModalOpen(true);
setModalContents(children);
};
const closeModal = () => setIsModalOpen(false);
const onDimmerClick = (event: React.MouseEvent<HTMLDivElement>) => {
if (event.currentTarget !== event.target) return;
closeModal();
};
// useMemo 사용
const memoValue = useMemo(() => {
return { isModalOpen, openModal, closeModal };
}, [isModalOpen]);
return (
<ModalContext.Provider value={memoValue}>
{children}
{isModalOpen && <div>{modalContents}</div>}
</ModalContext.Provider>
);
};
export function useModalAPI() {
return useContext(ModalContext);
}
UserObjContext.tsx
import React, { createContext, useState, useContext, useMemo } from 'react';
import { userObjType, UserObjContextValue } from '../../types/context';
export const UserObjContext = createContext<UserObjContextValue | null>(null);
export const UserObjProvider = ({ children }: { children: React.ReactNode }) => {
const [userObj, setUserObj] = useState<userObjType | null>(null);
// useMemo 사용
const memoValue = useMemo(() => {
return { userObj, setUserObj };
}, [userObj]);
return <UserObjContext.Provider value={memoValue}>{children}</UserObjContext.Provider>;
};
export function useUserObjAPI() {
return useContext(UserObjContext);
}
각 context의 value로 사용되는 값들을 useMemo훅으로 감싸주고
이로부터 나오는 결과값을 value에 지정해 주었다