useContext hook의 return 값은 useState와는 달리 context로 등록된 value 하나뿐입니다. 따라서 Provider에게 전달해준 value 자체를 수정할 방법은 없습니다. 그래서 리액트 공식 문서를 찾아보면 하위 컴포넌트에서 상위 컴포넌트에서 정의한 context를 수정하는 예시를 보여주고 있는데 예시의 핵심은 value안에 state와 setState를 모두 전달하는 것입니다.
Context 선언 하는 방법
export const ThemeContext = React.createContext({
theme: themes.dark,
toggleTheme: () => {},
});
상위 컴포넌트가 클래스형일 때 context를 제공하는 방식
class App extends React.Component {
constructor(props) {
super(props);
this.toggleTheme = () => {
this.setState(state => ({
theme:
state.theme === themes.dark
? themes.light
: themes.dark,
}));
};
// state에 업데이트 메서드도 포함되어있으므로
// 이 또한 context Provider를 통해 전달될것입니다.
this.state = {
theme: themes.light,
toggleTheme: this.toggleTheme,
};
}
render() {
// Provider에 state 전체를 넘겨줍니다.
return (
<ThemeContext.Provider value={this.state}>
<Content />
</ThemeContext.Provider>
);
}
}
이 예시를 보면 toggleTheme이라는 함수로 theme이라는 state를 변경하고 있습니다. 이와 같이 Provider에게 state, setState를 동시에 전달하면 됩니다.
상위 컴포넌트가 함수형일 때 context를 제공하는 방식
function App() {
const [theme, setTheme] = useState({themes.light});
const toggleTheme = () => {
setTheme((theme) => {
theme === themes.dark ? themes.light : themes.dark
});
};
return (
<ThemeContext.Provider value={{theme, toggleTheme}}>
<Content />
</ThemeContext.Provider>
);
}
상위 컴포넌트가 함수형일 때는 useState hook을 사용하여 코드가 짧아지고 이해하기 편하게 되었습니다. 핵심은 기존 클래스 방식에서는 constructor를 이용하여 그 안에서 state를 선언하고 setState를 이용하였던 것에서, 상위 함수형 컴포넌트에서 useState hook의 return값을 하위 컴포넌트에 전달을 하는 것으로 바꾼 것입니다.
예시의 toggleTheme 대신에 setTheme을 직접 전달해도 되고 다른 방식으로 수정해도 됩니다. 필요한 변경 방식을 함수로 만들어 내려주기만 하면 됩니다.
useContext를 사용하여 하위 컴포넌트에서 context를 수정하는 방법
import {ThemeContext} from './theme-context';
function ThemeTogglerButton() {
const {theme, toggleTheme} = useContext(ThemeContext)
// ThemeTogglerButton는 context로부터
// theme 값과 함께 toggleTheme 매서드도 받고 있습니다.
return (
<button
onClick={toggleTheme}
style={{backgroundColor: theme.background}}>
Toggle Theme
</button>
);
}
이와 같은 방식으로 state를 받고 state를 수정하시면 됩니다. 참고로 바로 위의 코드는 공식 홈페이지에 있는 내용을 hook 버전으로 변경한 것입니다. 여기서 주의할 사항은 useContext 를 받을 때는 [theme, toggleTheme]이 아니라 {theme, toggleTheme} 이라는 점입니다. useState hook이 아니라 Object 형태의 context를 풀어서 받기 위해서 저렇게 해야 합니다.
'HOW-TO GUIDES' 카테고리의 다른 글
react-csv에서 onClick 시점에 async로 데이터를 받아 오는 방법 (1) | 2021.09.16 |
---|---|
create-react-app + typescript + tailwindcss + eslint 한 번에 설정하는 법 (0) | 2021.08.15 |
ant design에서 여러 개의 input state를 관리하는 방법(in typescript react) (0) | 2021.08.15 |
M1 맥북에서 plantuml 사용하는 방법 (0) | 2021.08.11 |
next.js에서 타입스크립트 리액트 테스트 환경 셋업하기 (0) | 2021.08.07 |