React 16.6 Context API로 props drilling 해결하기
문제 상황
사용자 인증 정보를 최상위 App 컴포넌트에서 관리하고 있었는데, 이를 5단계 아래 컴포넌트에서 사용해야 했다. 중간 컴포넌트들은 해당 props를 사용하지 않으면서도 계속 전달만 해야 하는 상황이었다.
// 기존 방식
<App user={user}>
<Layout user={user}>
<Content user={user}>
<Article user={user}>
<CommentForm user={user} /> {/* 여기서만 실제 사용 */}
</Article>
</Content>
</Layout>
</App>
Context API 적용
React 16.3부터 정식 API로 제공되는 Context를 사용하기로 했다. 예전 context API는 불안정하다고 해서 사용을 망설였었는데, 이제는 공식 문서에서도 권장한다.
// UserContext.js
import React from 'react';
const UserContext = React.createContext(null);
export default UserContext;
// App.js
import UserContext from './UserContext';
class App extends React.Component {
state = {
user: { id: 1, name: 'John' }
};
render() {
return (
<UserContext.Provider value={this.state.user}>
<Layout>
<Content>
<Article>
<CommentForm />
</Article>
</Content>
</Layout>
</UserContext.Provider>
);
}
}
// CommentForm.js
import UserContext from './UserContext';
class CommentForm extends React.Component {
render() {
return (
<UserContext.Consumer>
{user => (
<div>
<p>작성자: {user.name}</p>
<textarea />
</div>
)}
</UserContext.Consumer>
);
}
}
결과
중간 컴포넌트들이 user props를 받을 필요가 없어졌다. 코드가 훨씬 간결해지고, 컴포넌트 시그니처가 명확해졌다. 다만 Consumer의 render props 패턴이 조금 장황한 감은 있다.
Redux를 쓰기에는 과한 상황에서 전역 상태 관리가 필요할 때 유용했다. 테마, 언어 설정 같은 것들도 Context로 관리하면 좋을 것 같다.