Recoil이란?
React.js를 만든 Facebook에서 만든 전역상태관리 라이브러리. 이 이상의 설명은 필요없을 듯 하다.
전역 상태란?
컴포넌트에서 쓰이는 상태값(state)가 아닌, 이곳저것에서 전역적으로 쓰이는 상태(state)를 말한다.
전역 상태를 사용하는 이유
굳이 안 써도 되긴 한다. 하지만 그렇게 된다면 서로 다른 컴포넌트끼리 특정한 값(= 상태 = state)를 공유하려면 공통된 상위 컴포넌트로부터 prop을 계속 전달하는 방법을 써야 하는데,
- 중간에 거치는 컴포넌트들마다 하나하나 prop을 전달하게끔 코드 작성하는거 귀찮음
- 중간에 거치는 컴포넌트들은 전달받은 prop을 하위 컴포넌트로 전달만 하고 사용은 안 할 수도. 즉 비효율적
- 중간에 거치는 컴포넌트들이 많아지면 나중엔 prop을 추적하기가 힘들어짐
이런 문제들이 있다. 이 때 전역적으로 쓰는 상태를 만든다면, 어느 컴포넌트에서나 전역 상태에 접근가능하므로 위에서 말한 불편들이 해소될 수 있다!
그럼 수많은 전역관리 툴 중 Recoil을 사용하는 이유?
일단 따지고보면 context API는 전역상태관리를 해주는 기능이라기보다는 단순히 전역적으로 상태를 공유하게끔 해주는 기능이라고 보는게 정확하다. context API를 사용해서도 전역상태값을 변경하는 건 물론 가능하지만, context API를 사용해 상태값을 변경하면 provider로 감싸져있는 컴포넌트들이 죄다 렌더링된다는 치명적 단점이 있다! (provider 하위에서 context를 구독하는 모든 컴포넌트는 provider의 value가 바뀔 때마다 다시 렌더링된다는 말)
// ContextTest.jsx
export const myContext = createContext("JOFE");
const ContextTest = (props) => {
const [name, setName] = useState("JOFE");
return (
<myContext.Provider value={[name, setName]}>
<Welcome />
<Hello />
</myContext.Provider>
)
}
// Welcome.jsx
const Welcome = (props) => {
const [name, setName] = useContext(myContext)
return (
<div>
<button onClick={() => {setName("Nunu")}}>이름바꾸기</button>
{name}
</div>
)
}
// Hello.jsx
const Hello = (props) => {
useEffect(() => {
console.log("Hello 렌더링")
})
return (
<>
</>
)
}
myContext라는 context의 value로 name이란 상태와 name을 변경해주는 세터함수를 넣어줬다. 그리고 이 context를 Welcome컴포넌트에서 사용하는 모습이다. Hello컴포넌트는 useEffect를 사용해서 렌더링될때마다 console에 Hello 렌더링이란 문구를 찍어준다.
이름바꾸기를 하면?
myContext를 사용하지 않는 Hello컴포넌트도 단순히 provider 안에 있다는 죄(?)로 다시 렌더링이 되는 모습을 확인할 수 있다..!
바로 여기서 Recoil이 이런 문제들을 해결해줄 수 있기 때문에 사용한다. 하단에서 보여드림.
Recoil 기초적인 사용법
일단 상위 컴포넌트에서 RecoilRoot란 컴포넌트로 애들을 감싸주면 된다.
import { RecoilRoot } from 'recoil';
function App() {
return (
<RecoilRoot>
<RecoilTest />
</RecoilRoot>
);
}
그리고 atoms.js파일을 만들어서 요로코롬 atom들을 만들어준다.
※ atom = Recoil에서 사용하는 상태들의 명칭이자 단위라고 생각하면 됨. 이 atom들의 key들은 각각 고유한 값이어야 함! 중복되면 안 된다는 뜻
// atoms.js
import { atom } from "recoil";
export const nameState = atom({
key: "name",
default: "JOFE"
});
참고로 굳이 atoms.js에 만들 필요는 없는데 이렇게 전역상태들을 한 파일에 관리해주는 게 더 편하다고 한다.
// RecoilTest.jsx
const RecoilTest = (props) => {
return (
<div>
<Welcome />
<Hello />
</div>
)
}
// Welcome.jsx
const Welcome = (props) => {
const [name, setName] = useRecoilState(nameState)
return (
<div>
<button onClick={() => {setName("Nunu")}}>이름바꾸기</button>
{name}
</div>
)
}
요로코롬 useRecoilState를 사용해서 React의 hook마냥 쓸 수 있다! React스럽다는게 최고 장점인 듯. 참고로 세터함수는 필요없고 값만 읽고 싶다면 useRecoilValue를 쓰면 된다.
암튼, 이렇게 하면
요로코롬 Hello컴포넌트는 리렌더링되지 않는다! 오직 해당 atom을 사용하는 애들만 바뀐다.
'WEB > REACT & NEXT' 카테고리의 다른 글
[React.js] React Router - useNavigate()와 useLocation()으로 데이터 주고받기 (0) | 2022.07.27 |
---|---|
[React.js] Ref는 뭐고 왜 쓰는 걸까 (0) | 2022.07.27 |
[React.js] 리액트에서 입력 폼 다루기(input태그들) - 1편 (0) | 2022.07.25 |
[짧][React.js] 렌더링이 2번 되는 현상 (0) | 2022.07.25 |
[React.js] useEffect 정리 (0) | 2022.07.13 |