-
recoil, recoil-persistFW, Lib 공부/React 2022. 7. 20. 16:12
useState의 사용이 익숙해질 무렵, 한 가지 불편함을 느꼈다.
부모 컴포넌트에서 자식 컴포넌트로 useState안의 값을 넘겨줘야 하는 경우, 부모-자식이 한 두 단계정도 떨어져 있을 때는 상관이 없는데, 3회 이상 상속을 시켜줘야 하는 경우에는 불편함이 많았다.
이 때, recoil을 알게 되었고, 불편함이 바로 해소되었다..!
recoil - 공식 문서 페이지
설치 | Recoil
NPM
recoiljs.org
recoil은 리액트를 위한 상태관리 라이브러리로, 기존에 쓰던 useState가 지역변수 같은 느낌이었다면, recoil은 전역변수 같은 느낌이었다.
그럴만 한게, recoil은 상태를 별도의 코드 파일로 작성하고, 어떠한 컴포넌트 파일에서 상태값을 불러오고, 수정할 수 있게 해준다.
뿐 만 아니라, 필터링의 기능도 구현할 수 있어, 리스트나 객체를 하나만 만들어서 여러 상황에 적용할 수 있기에 데이터 관리도 용이하다.
오늘 작성하는 내용은 내가 recoil을 쓰면서 가장 많이 사용했던 기능과 hook를 정리하고자 한다.
1. atom
atom은.. 생성자의 역할을 하는 함수이다.
인자로는 객체 하나를 받는데, 사용하야 하는 키 값이 정해져 있다.
key, default, effect_UNSTABLE 이렇게만 사용해봤다.
effect 대신에 effect_UNSTABLE을 사용했던 이유는 recoil-persist 때문인데, 자세한 내용은 뒤에서...
key는 atom의 고유 식별자로, 문자열을 값으로 받는다.
default는 초기화될 때, 기본으로 저장되는 값으로, 값, 배열, 객체 등을 값으로 받을 수 있다.
effect는 초기화될 때, 우선 순위에 따라 호출되는 atom effect 함수들의 배열을 참조할 수 있다.
export const categoriesState = atom<ICategories[]>({ key: "categories", default: [ { title: "To Do", id: 0 }, { title: "Doing", id: 1 }, { title: "Done", id: 2 }, ], effects_UNSTABLE: [persistCategory], });
이런식으로 사용한다.
이렇게 생성된 atom은 recoil에서 제공하는 여러 hook을 통해 접근, 수정이 가능하다.
1-1. useRecoilValue()
const category = useRecoilValue(categoryState);
useRecoilValue는 atom을 인자로 받고, 그 안에 저장되어 있는 데이터를 리턴해준다.
1-2. useSetRecoilState()
const setCategory = useSetRecoilState(categoryState); setCategory({key: value});
useSetRecoilState는 atom을 인자로 받고, 그 데이터를 수정할 수 있는 함수를 리턴해준다.
1-3. useRecoilState()
const [category, setCategory] = useRecoilState(categoryState);
useRecoilState는 atom을 인자로 받고, 그 안에 저장되어 있는 데이터와 수정할 수 있는 함수를 리턴해준다.
1-1, 1-2 내용을 모두 커버하고, useState와 사용방법도 동일하다.
2. selector
selector는 recoil에서 함수나, 파생된 상태를 나타낸다.
인자로는 역시 객체 하나를 받는데, 사용하야 하는 키 값이 정해져 있다.
key, get, set만 사용해봤다.
key는 atom의 고유 식별자로, 문자열을 값으로 받는다. 이 때, atom과 selector 사이의 키 값도 중복되선 안 된다.
get은 파생된 상태를 평가하는 함수를 값으로 받아야 한다. 이 때 첫 번째 매개변수로 get 함수를 포함한 객체를 받는데, 이 get 함수를 통해 다른 atom, selector에 접근할 수 있다.
set은 데이터를 변화시키는 함수를 값으로 받을 수 있다.이 때 첫 번째 매개변수로 set 함수를 포함한 객체를 받고, 두 번째 매개변수로 입력된 새로운 값을 받는데, 이 set 함수를 통해 다른 atom의 값을 변화시킬 수 있다.
const tempFahrenheit = atom({ key: 'tempFahrenheit', default: 32, }); const tempCelcius = selector({ key: 'tempCelcius', get: ({get}) => ((get(tempFahrenheit) - 32) * 5) / 9, set: ({set}, newValue) => set( tempFahrenheit, newValue instanceof DefaultValue ? newValue : (newValue * 9) / 5 + 32, ), });
이런식으로 사용한다.
참고로 위 코드같이 동기적인 처리 뿐 만 아니라, get으로 비동기적인 처리도 할 수 있으나, 직접 해본적은 아직 없기에 링크로만 남겨두겠다.
selector(options) | Recoil
Selector는 Recoil에서 함수나 파생된 상태를 나타낸다. 주어진 종속성 값 집합에 대해 항상 동일한 값을 반환하는 부작용이 없는 "순수함수"라고 생각하면 된다. get 함수만 제공되면 Selector는 읽기
recoiljs.org
2-1-1. get:
get: ({get}) => ((get(tempFahrenheit) - 32) * 5) / 9,
get 키 값은 함수를 값으로 받아야 한다.
이 때 받는 함수의 첫 번째 매개변수는 get 함수를 포함한 객체이다.
이 get 함수는 인자로 atom, 또는 selector을 전달해야 한다.
이 때, get으로 받은 recoil 상태로 조건문이나 filter을 걸어 결과에 따라 다르게 return 시키면 필터링 기능을 구현하게 되는 것이다.
2-1-2. set:
set: ({set}, newValue) => set( tempFahrenheit, newValue instanceof DefaultValue ? newValue : (newValue * 9) / 5 + 32, ),
set 키 값은 함수를 값으로 받아야 한다.
이 때 받는 함수의 첫 번째 매개변수는 set 함수를 포함한 객체이고, 두 번째 매개변수는 입력된 새로운 값이다.
두 번째 매개변수로 값을 전달하는 방법은 아래에 2-2-1에서 다룬다.
이 set 함수는 첫 번째 인자로 atom, 즉 recoil의 상태를 전달해야 하고, 두 번째 인자로 변화시킬 새로운 값을 전달해야 한다.
여기서 중요한 점은 두 번째 인자(newValue)인 새로운 값의 타입이다.
이 인자는 두 개의 타입 중 하나를 갖을 수 있는데,
첫 번째 경우는 위의 get 키로 받은 get 함수로 호출하는 atom, selector의 데이터 타입,
두 번째 경우는 DefaultValue이다.
만약 newValue가 useResetRecoilState()와 같이 selector를 재설정하는 인자가 들어오는 경우, newValue는 DefaultValue 클래스의 인스턴스이기 때문에, 이 때는 별도의 수정없이 newValue값을 그대로 전달해야 한다.
따라서 수정될 값을 set 함수의 두 번째 인자로 보내기 전에 newValue가 DefaultValue의 인스턴스인지를 검사하는 것이다.
2-2-1. useRecoilState()
const [tempC, setTempC] = useRecoilState(tempCelcius); const addTenCelcius = () => setTempC(tempC + 10);
selector도 atom과 마찬가지로 useRecoilState의 인자로 전달할 수 있다.
하지만 이렇게 selector를 사용할 경우 tempFahrenheit atom(실제 저장되는 데이터)을 1개만 가지고도 tempFahrenheit, tempCelcius 두 온도를 모두 보여주고, 변환 계산이 가능해진다.
recoil-persist - npm 페이지
recoil-persist
Package for recoil to persist and rehydrate store. Latest version: 4.2.0, last published: 2 months ago. Start using recoil-persist in your project by running `npm i recoil-persist`. There are 4 other projects in the npm registry using recoil-persist.
www.npmjs.com
recoil-persist는 recoil의 상태를 브라우저 Storage에 실시간으로 저장하고, 불러오게 해주는 라이브러리이다.
사용방법은 recoil atom함수로 전달하는 객체의 키 값으로 effect_UNSTABLE를 주고 값으로 전달되는 의존성 배열에 recoilPersist로 생성된 atomEffect를 넣어주면 된다.
const { persistAtom: persistCategory } = recoilPersist({ key: "categoryLocal", storage: localStorage, }); export const categoriesState = atom<ICategories[]>({ key: "categories", default: [ { title: "To Do", id: 0 }, { title: "Doing", id: 1 }, { title: "Done", id: 2 }, ], effects_UNSTABLE: [persistCategory], });
recoilPersist는 객체 하나를 인자로 받는데, 역시 사용해야 하는 키 값이 정해져 있다.
key, storage만 사용해봤다.
key는 recoil-persist 고유 식별자로, 문자열을 값으로 받는다.
storage는 브라우저 로컬 저장소의 위치를 지정한다. localStroage, localSession 등 지정할 수 있는데 localStorage만 사용해봤다.
기존에는 js로 길-게 쳐야했던 기능을 단 몇줄로 구현 가능하단 사실은 편하긴 했지만, 요근래 없데이트인 상태로 남아있기에...(포스트 작성일 기준, 최근 업데이트가 2달 전) 사용에 주의가 필요할 듯 하다.
요약
const tempFahrenheit = atom({ key: 'tempFahrenheit', default: 32, }); const tempCelcius = selector({ key: 'tempCelcius', get: ({get}) => ((get(tempFahrenheit) - 32) * 5) / 9, set: ({set}, newValue) => set( tempFahrenheit, newValue instanceof DefaultValue ? newValue : (newValue * 9) / 5 + 32, ), }); function TempCelcius() { const [tempF, setTempF] = useRecoilState(tempFahrenheit); const [tempC, setTempC] = useRecoilState(tempCelcius); const resetTemp = useResetRecoilState(tempCelcius); const addTenCelcius = () => setTempC(tempC + 10); const addTenFahrenheit = () => setTempF(tempF + 10); const reset = () => resetTemp(); ... }
'FW, Lib 공부 > React' 카테고리의 다른 글
styled-components (0) 2022.07.20 React 프로젝트 gh-pages 배포 (0) 2022.07.03 useRouteMatch() (0) 2022.06.22 useLocation() (0) 2022.06.22 useParams() (0) 2022.06.22