props
는 인접하지 않은 컴포넌트에게 데이터를 보내는 경우 이어지는 모든 컴포넌트에게 데이터 전달 작업을 일일이 해주어야 했습니다. 이어지는 과정에서 불필요한 작업이 많아지고, 정작 해당 컴포넌트에는 해당 props
데이터가 필요없음에도 굳이 일련의 과정을 위해 어쩔 수 없이 연결을 해주어야 했죠.
Context
는 부모 컴포넌트로부터 자식 컴포넌트로 전달되는 데이터의 흐름과는 상관없이 전역적인 데이터를 다룰 때 사용합니다. 전역 데이터를 Context
에 저장한 후, 데이터가 필요한 컴포넌트에서 해당 데이터를 불러와 사용할 수 있습니다. Context
를 사용하기 위해서는 Provider
와 Consumer
를 사용해야 합니다. 공통 부모 컴포넌트에 Context.Provider
를 랩핑하는 경우, 해당 부모 컴포넌트의 모든 자식은 Context
에 설정된 데이터에 접근하는 것이 가능해집니다.
// context.js
const AuthContext = React.createContext({
isLoggedIn: false,
onLogout: () => {},
onLogin: (emali, password) => {},
});
export default AuthContext;
// Provider.js
...
...
const [isLoggedIn, setIsLoggedIn] = useState(false);
...
...
return (
<AuthContext.Provider value={{isLoggedIn : isLoggedIn}}>
<MainHeader />
<main>
{!ctx.isLoggedIn && <Login />}
{ctx.isLoggedIn && <Home />}
</main>
<AuthContext.Provider/>
);
// Consumer.js
...
...
return (
<AuthContext.Consumer>
{(ctx) => {
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={props.onLogout}>Logout</button>
</li>
)}
</ul>
</nav>
);
}}
</AuthContext.Consumer>
);
좀 더 간단한 방법으로, useContext()
를 사용하는 방법이 있습니다. useContext()
를 활용하면 Consumer()
함수를 호출하지 않은 체, Provider
가 제공하는 데이터에 바로 접근할 수 있습니다.
const Navigation = () => {
const { isLoggedIn, onLogout } = useContext(AuthContext);
return (
<nav className={classes.nav}>
<ul>
{isLoggedIn && (
<li>
<a href="/">Users</a>
</li>
)}
{isLoggedIn && (
<li>
<a href="/">Admin</a>
</li>
)}
{isLoggedIn && (
<li>
<button onClick={onLogout}>Logout</button>
</li>
)}
</ul>
</nav>
);
};
사용자 정의 컨텍스트를 통해, App.js와 Context를 완전히 분리하는 코드가 있다. 난이도가 있으니, 나중에 다시 한번 꼭 보도록 하자.