-
React 상태 관리 : Recoil 로 해보자!Front-end/React 2021. 12. 4. 18:42반응형
일반적으로 많은 회사에서 redux, mobx를 사용하는 얘기는 들었다.
나 또한 Redux, mobx는 경험이 있지만 Recoil은 얘기만 들어봤지 사용해보진 않았는데 그래서 documentation을 따라해보면서 알아가보려고 한다.
나는 머리가 좋지 않다.
그래서 하나하나 잘 따져가면서 공부를 해야한다.
redux를 익힐 때 고생했던 경험을 살려... 이번에는 redux를 익혔을 때의 순서를 지켜가면서 공부를 해봐야겠다
About Recoil
우선 각 상태관리 라이브러리들의 architecture 에 대해서 머리에 그림을 그려야 한다.
Redux의 경우, Flux architecture를 기반으로 했고, mobX의 경우 Proxy, Context API는 context를 기반으로 했다.
그렇다면 Recoil은? 바로 Atomic 이다.
Recoil은 React를 만든 Facebook에서 만들었다.
그러므로 더 잘 어울리게 만들었을 것이라는 믿음이 생기는 부분이었다.
Recoil은 React의 내부 상태만을 이용하게 된다.
아주 작은 atom 단위로 관리되며, selector라는 순수함수를 제공한다.
상태가 변경되면 atom을 참조하는 component만 re-rendering 되기 때문에 re-render의 최소화를 기대할 수 있다.
Let's use Recoil
한글화로 문서화가 잘 되어 있어서 Recoil 시작하기를 통해서 도전해보자!
우선 얼핏봐도 Redux에 비해 런닝커브가 비교적 낮다는 것을 알 수 있다.
cra를 통해서 리액트를 설치하고,
yarn create react-app recoil-tutorial
recoil도 설치를 하자.
yarn add recoil
그리고 RecoilRoot를 만들어야 한다.
index.js에서 전체를 다 감싸주도록 하자.
// src > index.js import React from "react"; import ReactDOM from "react-dom"; import "./index.css"; import App from "./App"; import { RecoilRoot } from "recoil"; ReactDOM.render( <React.StrictMode> <RecoilRoot> <App /> </RecoilRoot> </React.StrictMode>, document.getElementById("root") );
components라는 폴더에 CharactorCounter.jsx, TextInput.jsx, CharacterCount.jsx를 만들어보자.
// src > components > TextInput.jsx import React from "react"; const TextInput = () => { return ( <div> TextInput </div> ); }; export default TextInput;
// src > components > CharacterCounter.jsx import React from "react"; const CharacterCounter = () => { return <div>character count : 0</div>; }; export default CharacterCounter;
// src > components > CharactorCounter.jsx import React from "react"; import CharacterCount from "./CharacterCount"; import TextInput from "./TextInput"; const ChrarctorCounter = () => { return ( <div> <TextInput /> <CharacterCount /> </div> ); }; export default ChrarctorCounter;
우선은 이렇게 만들어서 App.js에서 불러오자.
그리고 recoil 폴더를 만들어서 atom.js를 먼저 만들것이다.
// src > recoil > atom.js import { atom } from "recoil"; export const textState = atom({ key: "text", default: "", }); // key : Unique ID // default: initial value
atom은 이런 식으로 사용 할 수 있는데, key 값은 unique 해야하고, default 값은 initial value라고 생각하면 된다.
recoil의 atom은 state의 일부를 나타내는데 어떤 컴포넌트에서나 읽고 쓸 수 있다.
atom의 값을 읽게 되는 컴포넌트들은 암묵적으로 atom을 subscribe 한다.
그래서 atom의 업데이트는 subscribe 하고 있는 모든 컴포넌트를 re-rendering하게 만든다.
Atom이 만들어졌다면 Selector도 만들어보자.
selector는 atom state에 의존하는 동적인 데이터를 생성한다.
atom에 의존하므로 atom의 정보가 바뀌게 되면 selector도 자동으로 re-rendering 된다.
get이라는 함수를 사용하게 되어있는데 이를 통해서 atom의 정보를 가져올 수 있다.
그리고 set함수를 통해서 atom 정보를 업데이트 하도록 할 수 있다.
// src > recoil > selector.js import { selector } from "recoil"; import { textState } from "../atoms/atom"; export const charCountState = selector({ key: "charCountState", get: ({ get }) => { const text = get(textState); return text.length; }, });
그렇다면 이를 사용해보자.
[ 그 전에 잠깐!!! recoil에서 사용되어지는 hook을 짧게 살펴보자 ]
기본 값 대신 Recoil state를 인수로 받는다는 점만 제외하면 useState hook과 비슷하다고 볼 수 있다.
이는 컴포넌트가 상태를 읽고 쓰려고 할 때 사용이 권장 되어진다.example) const [text, setText] = useRecoilState(textState)
Recoil state value(subscribe하는 value)를 업데이트하기 위한 setter 함수를 반환한다.
이 hook은 컴포넌트가 상태를 읽지 않고 쓰기만 하려고 할 때 권장되어진다.
example) function Form() { const setNamesState = useSetRecoilState(namesState); return <FormContent setNamesState={setNamesState} />; }
위 예시의 컴포넌트는 마운트 될 때 한번만 랜더링 되어질 것이다.
주어진 Recoil state value를 반환한다.
이는 읽기 전용 상태, 쓰기 가능 상태에서 모두 동작하므로 컴포넌트가 상태를 읽을 수만 있게 하고 싶을 때 사용 권장이 되어지는 hook이다.
값의 업데이트를 할 필요 없는 경우 사용 할 수 있을 것이다.
또한 React에서 사용하면 상태가 업데이트 될 때 re-rendering 되도록 컴포넌트를 subscribe 하고, state가 error를 가지고 있거나, 보류 중인 비동기 resolution이 있다면 던져줄 수 있다.
이는 비동기 selector의 값을 읽기 위해 사용 된다.
상태를 기본값으로 reset 할 수 있게 해준다.
// example) import {todoListState} from "../atoms/todoListState"; const TodoResetButton = () => { const resetList = useResetRecoilState(todoListState); return <button onClick={resetList}>Reset</button>; };
다시 돌아와서, 앞서 만든 TextInput.jsx에 useRecoilState를 사용해볼 수 있다.
// src > components > TextInput.jsx import React from "react"; import { useRecoilState } from "recoil"; import { textState } from "../recoil/atoms/atom"; const TextInput = () => { const [stateText, setStateText] = useRecoilState(textState); const changeHandler = (e) => { setStateText(e.target.value); }; return ( <div> <input type="text" value={stateText} onChange={changeHandler} /> <br /> Echo: {stateText} </div> ); }; export default TextInput;
앞서 설명 했던 Recoil의 hook 중 useRecoilState를 사용해서 만들었다.
이어서 CharacterCount.jsx를 만들어보자
import React from "react"; import { useRecoilValue } from "recoil"; import { charCountState } from "../recoil/selectors/selector"; const CharacterCounter = () => { const count = useRecoilValue(charCountState); return <div>character count : {count}</div>; }; export default CharacterCounter;
이는 useRecoilValue를 사용하여서 만들 수 있다.
그러면 아래처럼 사용이 가능하다.
이것이 Recoil의 기초적인 사용 방법이다.
반응형'Front-end > React' 카테고리의 다른 글
LocalStorage로 저장, 불러오기, 삭제 (JS, React) (2) 2023.02.05 리액트 파일 업로드, 파일 다운로드 File upload, download with javascript react (2) 2022.06.24 캘린더 날짜 바꾸기 - Welcome to Data structure (0) 2021.09.15 React - context API를 사용해보자! (0) 2021.09.07 portals을 이용한 리액트 모달창(modal) 만들기 (0) 2021.07.06