context를 통해 전달된 데이터 업데이트하기
시간이 지남에 따라 데이터를 동적으로 업데이트 하는 방법을 단계별로 풀어서 설명해보자.
먼저 Context를 생성하고, Provider를 설정한다. Provider은 Context를 사용하고자 하는 컴포넌트들에게 데이터를 공급하는 역할을 하는데 , 여기서 state 변수를 선언하고 이를 Context의 value로 전달한다.
이제 자식 컴포넌트에서 Context를 사용하여 데이터를 가져오고, 필요할 때 데이터를 업데이트 할 수 있다.
마지막으로 최상위 컴포넌트에서 Provider를 사용하여 전체 애플리케이션에 Context를 공급한다.
function MyPage() {
const [theme, setTheme] = useState('dark');
return (
<ThemeContext.Provider value={theme}>
<Form />
<Button onClick={() => {
setTheme('light');
}}>
Switch to light theme
</Button>
</ThemeContext.Provider>
);
}
이제 provider 내부의 모든 Button은 현재 theme값을 받게 된다. provider에게 전달한 theme값을 업데이트 하기 위해 setTheme를 호출하면 모든 Button 컴포넌트가 새로운 light 값으로 리렌더링 한다.
fallback 기본값 지정하기
React가 부모트리에서 특정 context의 provider들을 찾을 수 없는 경우, useContext()가 반환하는 context값은 해당 context를 생성할 때 지정한 기본값과 동일하다.
const ThemeContext = createContext(null);
기본값은 절대 변경되지 않는다.
null 대신 기본값으로 사용할 수 있는 더 의미있는값이 있는 경우가 많다. 예를들어,
onst ThemeContext = createContext('light');
이렇게 하면 실수로 해당 provider없이 일부 컴포넌트를 렌더링해도 중단되지 않는다. 또한 테스트 환경에서 많은 provider를 설정하지 않고도 컴포넌트가 테스트 환경에서 잘 작동하는 데 도움이 된다.
트리 일부에 대한 context 재정의하기
트리의 일부분을 다른 값의 provider로 감싸 해당 부분에 대한 context를 재정의 할 수 있다.
<ThemeContext.Provider value="dark">
...
<ThemeContext.Provider value="light">
<Footer />
</ThemeContext.Provider>
...
</ThemeContext.Provider>
필요한 만큼 porvider들을 중첩하고 재정의할 수 있다.
객체 및 함수 전달 시 리렌더링 최적화
context를 통해 객체와 함수를 포함한 모든 값을 전달할 수 있다.
function MyApp() {
const [currentUser, setCurrentUser] = useState(null);
function login(response) {
storeCredentials(response.credentials);
setCurrentUser(response.user);
}
return (
<AuthContext.Provider value={{ currentUser, login }}>
<Page />
</AuthContext.Provider>
);
}
여기서 context값은 두 개의 프로퍼티를 가진 JavaScript 객체이며, 그 중 하나는 함수이다. MyApp이 리렌더링 할 때마다(라우트 업데이트), 이것은 다른 함수를 가리키는 다른 객체가 될 것이므로 React는 useContext(AuthContext)를 호출하는 트리 깊숙한 곳의 모든 컴포넌트도 리렌더링해야 한다.
소규모 앱에서는 문제가 되지 않는다. 그러나 currentUser와 같은 기초 데이터가 변경되지 않았다면 리렌더링 할 필요가 없다. React가 ㅅ활용할 수 있도록 login함수를 useCallback으로 감싸고 객체 생성은 useMemo로 감싸면 된다. 이것은 성능 최적화를 위한 것이다.
import { useCallback, useMemo } from 'react';
function MyApp() {
const [currentUser, setCurrentUser] = useState(null);
const login = useCallback((response) => {
storeCredentials(response.credentials);
setCurrentUser(response.user);
}, []);
const contextValue = useMemo(() => ({
currentUser,
login
}), [currentUser, login]);
return (
<AuthContext.Provider value={contextValue}>
<Page />
</AuthContext.Provider>
);
}
이 변경으로 인해 MyApp이 리렌더링해야 하는 경우에도 currentUser가 변경되지 않는 한 useContext(AuthProvider)를 호출하는 컴포넌트는 리렌더링 할 필요가 없다.
'React 공식문서 스터디' 카테고리의 다른 글
useRef (2) (0) | 2024.05.30 |
---|---|
useRef (0) | 2024.05.29 |
useContext (0) | 2024.05.27 |
useReducer (2) (0) | 2024.05.23 |
useReducer 공식문서 스터디(1) (0) | 2024.05.22 |