Next.js로 토이프로젝트를 만들면서 전역상태관리가 필요해서 useContext를 사용해봤다.
평소에 Redux-toolkit만 사용했는데 이번엔 관리할 데이터가 적어서 굳이 redux를 사용하는것보단 react에서 제공되는 useContext를 사용하는게 간편하기도하고 코드도 간단해 보여서 사용하게 됐다.
내가 관리할 데이터는 [[1,2,3,4], [5,6,7,8]]과 같은 number 배열로 이루어진 배열이었다.
createContext를 import해서 context를 만들어준다. 초기값을 지정해주고 context에 전달한다.
// context/ResultContext.tsx
import { createContext } from "react";
interface ResultContextType {
numbers: number[][];
addNumbers: (arr: number[]) => void;
resetNumbers: () => void;
deleteNumbers: (idx: number) => void;
}
const ResultContext = createContext<ResultContextType>({
numbers: [],
addNumbers: (arr: number[]) => {},
resetNumbers: () => {},
deleteNumbers: (idx: number) => {},
});
export default ResultContext;
_app.tsx에서 useState를 이용해 상태값과 필요한 업데이트 함수를 작성해주고
ResultContext.Provider의 value에 전달해주면 된다.
context provider를 통해 value를 전달해주게되면
해당 컴포넌트의 하위컴포넌트에서 전역상태값에 접근할 수 있다.
_app.tsx에서 구성했기 때문에 모든 페이지에서 접근이 가능하다.
// _app.tsx
import ResultContext from "../components/context/ResultContext";
import { useState } from "react";
import { AppProps } from "next/app";
function App({ Component, pageProps }: AppProps) {
const [numbers, setNumbers] = useState<number[][]>([]);
const addNumbers = (arr: number[]) => {
setNumbers((prev) => [arr, ...prev]);
};
const resetNumbers = () => {
setNumbers([]);
};
const deleteNumbers = (idx: number): void => {
setNumbers(numbers.filter((el, index) => idx !== index));
};
...
return (
<ResultContext.Provider
value={{ numbers, addNumbers, resetNumbers, deleteNumbers }}
>
<Component {...pageProps} />
</ResultContext.Provider>
)
};
export default App;
필요한곳에서 useContext를 이용하면 상태값을 불러올 수 있다. 상태값을 업데이트 함수도 마찬가지로
const { addNumbers, deleteNumbers } = useContext(resultContext);
와 같이 불러와서 사용하면 된다.
import { useContext } from "react";
import resultContext from "../components/context/ResultContext";
import Num from "./Num";
function ResultList({ isSearch, search, searchId, findDrwNo }: Props) {
const { numbers } = useContext(resultContext);
return (
<>
{numbers.map((el, idx) => (
<div className="result-number">
{el.map((num, idx) => (
<Num key={idx} num={num} row={idx} />
))}
</div>
))}
</>
}