Context로 state 관리

gyojinnK·2024년 1월 14일

리액트 플러스

목록 보기
5/11
post-thumbnail

상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달하거나 받으면서 항상 props chain을 이용했었다.
이때 유쾌하지 못한 부분이 발생하는데 여러 하위 컴포넌트 중 낮은 레벨 수준의 컴포넌트로 데이터를 전달할 때 해당 state를 직접 사용하지 않는 컴포넌트들도 props를 통해서 state를 전달하는 로직을 수행해야하는 점이다.

이번엔 간단한 로그인 프로그램을 이용하여 하위 컴포넌트 중 해당 데이터를 사용하는 컴포넌트에서만 데이터에 접근할 수 있도록 Context를 이용해 보겠다.


Context 생성하기

먼저 src 디렉토리에 store라는 디렉토리를 만들자
여기에 Context를 만들어 저장할 것이다.

  • store 디렉토리 생성
  • createContext()를 이용하여 Context 생성
  • 관리할 state명과 기본값 생성
    • 예시 코드에서와 같이 함수도 가능
    • Context에 객체를 선언하여 리액트에게 알리기
// AuthContext.js
import React from "react";

// context 기본 객체 생성
const AuthContext = React.createContext({
    isLoggedIn: false,
    onLogout: () => {},
});

export default AuthContext;

여기서 해당 코드는 컴포넌트는 아닌 객체이다.
하지만 나중에 컴포넌트를 포함 할 것이다.


Context 공급하기

정의한 Context를 사용하려면 이를 리스닝할 요소들을 JSX로 감싸주어야 한다.

const [isLoggedIn, setIsLoggedIn] = useState(false);
const logoutHandler = () => {
    localStorage.removeItem("isLoggedIn");
    setIsLoggedIn(false);
};
<...>
<AuthContext.Provider
            value={{
                isLoggedIn: isLoggedIn,
                onLogout: logoutHandler,
            }}
        >
            <MainHeader />
            <main>
                {!isLoggedIn && <Login onLogin={loginHandler} />}
                {isLoggedIn && <Home onLogout={logoutHandler} />}
            </main>
        </AuthContext.Provider>

위에서 언급했듯이 AuthContext는 컴포넌트가 아니다.
하지만 Context의 속성인 Provider를 이용해서 컴포넌트로 사용할 수 있다.
Provider는 말 그대로 공급자로 감싸진 모든 컴포넌트에서 해당 context를 이용할 수 있게 해준다.
이후 value prop를 이용하여 이전에 정의해둔 Context 속 state값을 실제 state 값으로 초기화하여 사용한다.


Context 사용하기

공급했다면 useContext 훅을 이용하여 사용해보자.

  • ctx라는 이름으로 useContext에 Context 객체를 담아 저장한다.
  • 이전 props.으로 받아오던 값을 ctx.으로 변경한다.
import React, { useContext } from "react";

import classes from "./Navigation.module.css";
import AuthContext from "../../store/auth-context";

const Navigation = () => {
    const ctx = useContext(AuthContext);
    return (
        <nav className={classes.nav}>
            <ul>
                {ctx.isLoggedIn && (
                    <li>
                        <a href="/">Users</a>
                    </li>
                )}
                {ctx.isLoggedIn && (
                    <li>
                        <a href="/">Admin</a>
                    </li>
                )}
                {ctx.isLoggedIn && (
                    <li>
                        <button onClick={ctx.onLogout}>Logout</button>
                    </li>
                )}
            </ul>
        </nav>
    );
};

이렇게 수행하면 Context를 이용해서 원하는 state값을 원하는 하위 컴포넌트에서 prop chain을 이용하지 않고 직접 접근할 수 있다.

Context는 매우 유용해 보이지만 많은 컴포넌트들을 거쳐 prop을 전달해야하는 경우 외에 무분별한 사용은 오히려 독이 될 수 있다.
prop은 컴포넌트를 구성하고 그것들을 재사용할 수 있도록 하는 매커니즘이기 때문이다.

profile
기록하고 꺼내보고

0개의 댓글