앞서 우리는 props를 필요한 컴포넌트간 direct로 연결되는 건 불가능하다고 했다.
그러면 프로젝트규모가 커지면 몇가지 문제점이 생기는데 너무 많은 불필요한 함수들이 생긴다는 것이다. 단지 data를 옮기려고.
그래서 실제로 필요한 데이터를 부모로부터 받는 컴포넌트에서만 사용할 수 있으면 더 좋을 것이다. 부모를 통해 데이터를 전달하지 않도록, 부모는 데이터를 관리하지도 필요하지도 않으니까.
이를 위해 컴포넌트 전체에서 사용할 수 있는, 리액트에 내장된, 내부적인 state 저장소가 있다.
그것이 바로 리액트 컨텍스트라는 개념이다.
.
으로 컴포넌트를 포함하는 해당 객체의 속성에 접근할 수 있다. 그것이 바로 provider이다. 쉽게말해 바로 얘가 컴포넌트로 바꿔주는 속성이다. 값
을 value
prop으로 보내준다.export const 컴포넌트명 = React.createContext({
초기키값: 초기밸류(배열, 객체 아무거나)
});
export default props => {
const [스테이트값, set스테이트] = useState([{
객체1
},
{
객체2
},
{
객체3
},
{
객체4
}])
return (
<컴포넌트명.Provider value={{ 키캆: 스테이트값 }}>
{props.children}
</컴포넌트명.Provider >
);
};
import 아무이름Provider from "해당경로"
.. 로직 ..
return (
<아무이름Provider><다양한_컴포넌트></아무이름Provider>
)
import React, {useState, useEffect} from "react";
const AuthContext = React.createContext({
isLoggedIn: false,
onLogout: () => {},
onLogin: (email, password) => {}
});
export const AuthContextProvider = props => {
const [isLoggedIn, setIsLoggedIn] = useState(false);
useEffect(() => {
const storedUser = localStorage.getItem("isLoggedIn");
if (storedUser === "1") {
setIsLoggedIn(true);
}
}, [])
const logoutHandler = () => {
localStorage.removeItem("isLoggedIn");
setIsLoggedIn(false);
}
const loginHandler = () => {
localStorage.setItem("isLoggedIn", "1")
setIsLoggedIn(true);
}
return <AuthContext.Provider value={{
isLoggedIn: isLoggedIn,
onLogout: logoutHandler,
onLogin: loginHandler
}}>{props.children}</AuthContext.Provider>
}
export default AuthContext;
state 변경이 잦은 경우에는, 리액트 컨텍스트는 그다지 적합하지 않다.
예를 들어, 매초 또는 1초에 여러 번 state가 변경되는 경우이다.
로그인 같은 경우에는 1초에 여러번 바뀔일이 없기 때문에 이런 경우는 컨텍스트를 사용하면 좋다.
그러나 state가 훨씬 더 자주 바뀌는 경우에는 리액트 컨텍스트는 이에 최적화되어 있지 않다.
리액트의 context API가 작동하는 방식이 context에서 무언가 변경되었을 때 이 컨텍스트를 사용하는 어떤 컴포넌트가 관련이 있는 건지 어떤 컴포넌트가 관련이 없는 건지 알아내는 똑부러진 방법을 가지고 있지 않는다.
그 말인 즉, 컨텍스트 안의 어떤 항목을 변경하게 되면 직접적으로 영향을 받았는지 여부와는 상관 없이 useContext를 사용하는 모든 컴포넌트가 다시 빌드 되고, 다시 렌더링 된다는 것이다.
그리고 앞서 언급했듯 리액트의 context API는 일반적으로 최적화되어 있지 않는다.
앱의 전역적 state 관리 도구로 쓰이도록 만들어지지 않았다는 말이다.
인증 상태나 테마와 같은 일부 state를 위해 만들어졌다.
이 경우엔 리덕스를 사용하면 되고 포스팅을 확인하면 된다.
하지만 역시 앞서 언급했듯 만약 props chain이 매우 길어질 경우에는 아주 유용하게 사용될 수 있다.
1. 리액트 훅은 리액트 함수에서만 호출해야 한다. 즉, 컴포넌트 함수에서 또는 사용자 훅에서
2. 리액트 훅은 리액트 컴포넌트 함수 또는 사용자 정의 훅 함수의 최상위 수준에서만 호출해야 한다
예를 들어 중첩 함수(혹은 콜백함수)에서 훅을 호출하지 말고, block 문에서 호출하지 마라는 뜻이다.