일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 자바스크립트
- web
- 웹디자인기능사
- 코딩독학
- 렛츠기릿자바스크립트
- 세로메뉴바
- git
- 깃
- 웹디실기
- 생활코딩
- JavaScript
- 실기
- react
- 비전공자
- JS
- HTML
- 웹퍼블리셔
- jQuery
- CSS
- 정보처리기사
- 웹디자인기능사실기
- 코드공유
- 리액트
- 프론트엔드
- Supabase
- 연산자
- github
- 슬라이드전환
- 타입스크립트
- PROJECT
- Today
- Total
코딩하는라민
[React] Recoil 상태 관리 라이브러리 설치 및 기본 본문
[React] Recoil 상태 관리 라이브러리 설치 및 기본
📌 상태관리란?
상태는 컴포넌트 내부에서 변경이 일어나는 값을 관리하기 위한 모든 데이터를 말한다.
상태관리는 변경이 일어나는 값들을 관리하는 것이다.
상태관리는
- 초기값을 저장할 수 있어야 하고,
- 현재값을 읽을 수 있어야 하고,
- 값을 업데이트할 수 있어야 한다.
함수형 컴포넌트에서 useState 로 자식 컴포넌트에서 부모 컴포넌트의 state 를 변경하여 상태관리를 할 수 있었다.
또 다른 방법이 하나 더 있는데 바로 상태관리 툴을 이용하는 것이다.
상태관리 툴은 다양한 종류가 존재한다.
- Redux
- Recoil
- React query
- MobX
- apollo
- useSWR
- ...
📌 상태 공유 기능의 한계
기존에 사용하던 방식은 다음과 같은 한계점이 있다.
- 컴포넌트의 상태는 공통된 상위 요소까지 끌어올리기를 해야 공유될 수 있다.
그 과정에서 props drilling 이라는 문제점이 생겨서 성능 저하의 원인이 되기도 한다. - Context 를 이용해 위와 같은 문제점을 해결할 수 있지만, Context 는 단일 값만 저장할 수 있다는 단점이 있다.
위의 두 가지 특성이 state 가 존재하는 트리의 최상단 컴포넌트부터 state 가 사용되는 트리의 말단까지의 코드 분할을 어렵게한다.
📌 Recoil 이란?
2021 년에 페이스북에서 나온 리액트를 위한 상태관리 라이브러리이다.
Recoil 의 핵심은 Atoms 과 Selectors 로 이루어져있다.
Recoil 을 사용하면 Atoms 에서 selectors 를 거쳐 리액트 컴포넌트로 내려가는 데이터 흐름 그래프를 만들 수 있다.
Atoms | Selectors |
공유 상태 | 순수 함수 |
컴포넌트가 구독할 수 있는 상태 단위 | Atoms 상태 값을 동기 또는 비동기 방식으로 전환 |
📌 Recoil 설치하기
✅ NPM 설치
npm install recoil
or
yarn add recoil
Recoil 을 사용하려면 React 가 설치되어 있어야 한다.
Recoil 은 웹팩이나 롤업과 같은 모듈 번들러와도 문제 없이 호환이 가능하다.
✅ CDN
<script src="https://cdn.jsdelivr.net/npm/recoil@0.0.11/umd/recoil.production.js"></script>
✅ ESLint
💡 ESLint 플러그인 설치하기
npm init @eslint/config
💡 eslint-plugin-react-hooks 플러그인 설치하기
npm i -D eslint-plugin-react-hooks
이 플러그인을 설치하게 되면 컴포넌트에 훅 등을 import 하지 않았을 경우 eslint 가 경고하며 알려준다.
💡 .eslintrc.cjs 파일 설정
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react/jsx-runtime',
'plugin:react-hooks/recommended',
],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 'latest',
sourceType: 'module',
},
plugins: ['react', 'react-hooks'],
rules: {
'react/prop-types': 'off',
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': [
'warn',
{
additionalHooks: 'useRecoilCallback',
},
],
},
};
📌 Recoil 사용하기
✅ RecoilRoot
recoil 상태를 사용하는 컴포넌트는 루트 컴포넌트에 RecoilRoot 가 필요하다.
FontButton 컴포넌트에 recoil 을 사용한다면 이를 감싸주는 곳에서 RecoilRoot 를 써줘야하는 것이다.
즉, Recoil의 hooks를 사용하는 모든 구성 요소의 조상이어야 한다.
import React from 'react';
import {
RecoilRoot,
atom,
selector,
useRecoilState,
useRecoilValue,
} from 'recoil';
function App() {
return (
<RecoilRoot>
<FontButton />
<Text />
</RecoilRoot>
);
}
<RecoilRoot>는 여러개가 같이 존재할 수 있고, 각각이 독립적인 atom 상태의 providers/store가 된다.
📌 Atoms
Atoms 는 상태(state)의 일부를 나타낸다.
Atoms 는 컴포넌트가 구독할 수 있는 상태 단위인데, 업데이트와 구독이 가능하다.
Atoms 는 어떤 컴포넌트에서나 읽고 쓸 수 있다.
atom 의 값을 읽는 컴포넌트들은 암묵적으로 atom을 구독한다.
- atoms 이 업데이트되면 구독중인 컴포넌트들은 리렌더링된다.
- 런타임에서 생성될 수도 있음
- 동일한 atoms 가 여러 컴포넌트에서 사용 되는 경우 모든 컴포넌트는 상태를 공유
✅ Atoms 는 atom 함수를 사용해 생성
atom 함수는 쓰기 가능한 RecoilState 객체를 반환한다.
const fontSizeState = atom({
key: 'fontSizeState',
default: 14,
});
- key : 내부적으로 atom 을 식별하는데 사용되는 고유한 문자열. key 값은 전역적으로 고유하도록 설정해야한다.
- default : atom의 초기값 또는 promise 또는 동일한 타입의 값을 나타내는 다른 atom 이나 selector.
atom 을 읽고 쓰려면 useRecoilState() 라는 훅을 사용한다.
useRecoilState() 는 상태가 컴포넌트 간에 공유될 수 있다.
atom 함수를 정의한 변수를 useRecoilState 의 인자에 넣어준다.
function FontButton() {
const [fontSize, setFontSize] = useRecoilState(fontSizeState);
return (
<button onClick={() => setFontSize((size) => size + 1)} style={{fontSize}}>
Click to Enlarge
</button>
);
}
버튼을 클릭하면 폰트 사이즈가 1씩 증가한다.
폰트 사이즈의 기본값은 14이므로 버튼을 누르면 14부터 1씩 증가하게 된다.
버튼의 style 은 인라인의 형태로 사용했다.
function Text() {
const [fontSize, setFontSize] = useRecoilState(fontSizeState);
return <p style={{fontSize}}>This text will increase in size too.</p>;
}
Text 컴포넌트에서도 폰트 사이즈 스타일을 적용할 수 있다.
📌 Selectors
Selector 는 atoms 나 다른 selectors 를 입력으로 받아 파생된 상태를 생성하는 순수 함수이다.
주어진 종속성 값 집합에 대해 항상 동일한 값을 반환하는 부작용이 없는 함수를 말한다.
Selector는 파생된 상태(derived state)의 일부를 나타낸다.
파생된 상태란 상태의 변화이다.
- atoms 와 마찬가지로 상위의 atoms, selectors 가 업데이트되면 하위 selector 함수도 다시 실행된다.
- 컴포넌트들은 selectors를 atoms처럼 구독할 수 있다.
- selectors 가 변경되면 구독중인 컴포넌트들도 리렌더링된다.
✅ Selectors 는 selector 함수를 사용해 정의
get 함수만 제공되면 Selector 는 읽기만 가능한 RecoilValueReadOnly 객체를 반환한다.
set 함수 또한 제공되면 Selector 는 쓰기 가능한 RecoilState 객체를 반환한다.
Atoms 와 마찬가지로 고유한 key 설정이 필요하다.
get 메서드 내부에서 사용되는 get 함수는 Atoms 또는 다른 Selector를 전달받을 수 있다.
그럴 경우 자동으로 종속 관계가 생성되며, 참조했던 다른 Atoms, Selectors 가 업데이트 되면 다시 실행된다.
const fontSizeLabelState = selector({
key: 'fontSizeLabelState',
get: ({get}) => {
const fontSize = get(fontSizeState);
const unit = 'px';
return `${fontSize}${unit}`;
},
});
- key : 내부적으로 atom 을 식별하는데 사용되는 고유한 문자열. 애플리케이션 전체에서 다른 atom 과 selector에 대해 고유해야한다.
- get : 파생된 상태의 값을 평가하는 함수. 값을 직접 반환하거나 비동기적인 promise나 또는 같은 유형을 나타내는 다른 atom이나 selector 를 반환할 수 있다. 첫번째 매개변수로 다음 속성을 포함하는 객체를 전달한다.
- get : 다른 atom 이나 selector 로부터 값을 찾는데 사용되는 함수. 이 함수에 전달된 모든 atom과 selector는 암시적으로 selector에 대한 의존성 목록에 추가된다. Selector의 의존성이 변경되면 Selector 가 다시 평가된다.
- set : 이 속성이 설정되면 selector 는 쓰기 가능한 상태를 반환한다. 첫번째 매개변수로 콜백 객체와 새로 입력 값이 전달된다. 콜백에는 다음이 포함된다.
- get : 다른 atom 이나 selector로부터 값을 찾는데 사용되는 함수. 이 함수는 selector를 주어진 atom 이나 selector를 구독하지 않는다.
- set : 업스트림 Recoil 상태의 값을 설정할 때 사용되는 함수. 첫번째 매개변수는 Recoil 상태, 두 번째 매개변수는 새로운 값이다. 새로운 값은 업데이트 함수나 재설정 액션을 전파하는 DefalutValue 객체일 수 있다.
fontSizeLabelState(selector) 는 useRecoilValue() 를 사용해 읽을 수 있다.
useRecoilValue() 는 하나의 atom 이나 selector 를 인자로 받아 대응하는 값을 반환한다.
현재 상태에서는 fontSizeLabelState selector 는 읽을수만 있기 때문에 useRecoilState를 이용하지 않았다.
물론 useRecoilState 를 사용해서 인자 하나만 입력해서 사용할 수는 있다.
function FontButton() {
const [fontSize, setFontSize] = useRecoilState(fontSizeState);
const fontSizeLabel = useRecoilValue(fontSizeLabelState);
return (
<>
<div>Current font size: ${fontSizeLabel}</div>
<button onClick={setFontSize(fontSize + 1)} style={{fontSize}}>
Click to Enlarge
</button>
</>
);
}
버튼를 클릭하면 버튼의 글꼴 크기가 증가하는 동시에
현재 글꼴 크기를 반영하도록 글꼴 크기 레이블을 업데이트하는 두 가지 작업이 수행된다.
+
✅ 결국 selector 란?
처음에 공식문서에서 Selector 에 대해 읽어보고 정리해보았지만, 완벽하게 이해된 상태는 아니었다.
Selector 를 사용한 다른 블로그, 유튜브 예제들을 보면서 '파생된 상태'라는 말에 대해 조금은 이해가 되었다.
'파생되다' 라는 '어떤 근본이 되는 어떤 것으로부터 갈라져 나와 생기다'의 의미이다.
따라서 Selector 는 atom 에서 갈라져서 나와 생긴 것으로 atom 의 값을 가지고 조작해줄 수 있는 것으로 이해했다.
따라서 엑셀의 수식처럼 atom 의 값에 2배를 하는 함수를 반환하고싶다! 한다면 selector 를 이용해 useRecoilValue 를 이용해서 그 값을 2배로 만들어주도록 정의해줄 수 있다.
...
참고 : 리코일 공식 문서
등을 공부하고, 간단하게 정리한 내용입니다. 잘못된 부분이나 문제되는 점이 있으면 댓글 부탁드립니다.