• React

[React] Recoil 상태관리 라이브러리 기초

man_on 2022. 9. 11. 23:42
반응형

 

 

 

하단의 다크모드 버튼을 누르시면 좀 더 편안하게 보실 수 있습니다.

 

 

     


     

    Recoil

     

     

    React의 기존의 상태관리 라이브러리

     

    component state는 공통된 상위요소까지 끌어올려야 공유가능 → 거대한 트리가 re-render 될 수 있다는 단점

    Redux → 기본적인 store 구성을 위해 많은 보일러 플레이트와 많은 코드를 작성해야하는 단점

    Context → single value만 저장할 수 있으며, 자체 consumer를 가지는 여러 값들의 집합을 담을 수 없다는 단점

     

    이러한 단점을 해결하는 방안으로 facebook에서 만든 상태관리 라이브러리가 Recoil이다.

     

     

     

     

    Recoil의 장점

    1. 쉽다.

    2. 비동기 데이터 흐름을 위한 내장 솔루션 제공

    3. React 동시성 모드(Concurrent Mode) 지원 및 다른 새로운 React 기능과의 호환 가능성

     

     

     

     

     

    설치

    npm install recoil
    yarn add recoil

     

     

     

    RecoilRoot

    recoil state를 사용할 컴포넌트의 부모 tree에 RecoilRoot가 필요하다.

    import React from 'react';
    import { RecoilRoot } from 'recoil';
    import CahracterCounter from './CharacterCounter';
    
    const App = () => {
      return (
        <RecoilRoot>
          <CahracterCounter />
        </RecoilRoot>
      );
    };
    
    export default App;

     

     

     

     

     


     

     

     

     

     

     

    Atoms & Selectors

     

     

     

    기본 흐름

    Atoms에서 selectors(순수함수)를 거쳐 React components로 내려가는 data-flow

     

     

     

     

    Atom

    • Atoms는 어떤 component에서나 읽고 쓸 수 있는 하나의 state를 의미한다. (상태의 단위, 업데이트와 구독 가능)
    • Atom에 어떤 변화가 있으면 그 atom을 구독하는 모든 컴포넌트들은 re-rendering된다.
    • Atom을 생성하기위해 고유한 key 값과 default값을 설정해준다.
    • default값은 정적인 값, 함수, 비동기함수가 될 수 있다.
    const textState = atom({
      key: 'textState', // unique ID (with respect to other atoms/selectors)
      default: '', // default value (aka initial value)
    });

     

     

     

     

     

     

     

    Selector

    • Selector는 derived state(파생된 상태)의 일부를 나타낸다.
    • 파생된 상태를 수정하는 pure function 순수함수에 전달된 상태의 결과물이다.
    • 상위의 atoms, selectors가 업데이트 되면 하위의 selector 함수도 re-evalutated된다.
    • 최소한의 state만 atoms에 저장하고 다른 모든 파생되는 데이터는 selectors에 명시한 함수를 통해 효율적으로 계산하여 불필요한 state의 보존을 방지한다.

     

    //selector 함수로 정의한다.
    const fontSizeLabelState = selector({
      key: 'fontSizeLabelState',
    //전달되는 get 인자를 통해 atoms와 다른 selectors에 접근가능
      get: ({get}) => {
        const fontSize = get(fontSizeState);
        const unit = 'px';
    
        return `${fontSize}${unit}`;
      },
    });

     

     

     

     

     

     

     

     

     

     

     


     

     

     

     

     

     

    🔻 Hook

     

     

     

     

    • useRecoilState : 읽기/쓰기
    • useRecoilValue : 읽기
    • useSetRecoilState : 쓰기

     

     

     

     

    useRecoilState

    : atom 혹은 selector의 값을 읽고 쓸 때 사용한다.

    useState와 동일하게 사용가능하다.

    const [count, setCount] = useRecoilState(countState);
    
    const increaseCount = () => {
    	setCount(count + 1);
    }

     

    [활용]

    import React from 'react';
    import { useRecoilState } from 'recoil';
    import { todoListState } from '../recoil';
    
    export const TodoItem = ({ item }) => {
      const [todoList, setTodoList] = useRecoilState(todoListState);
      const index = todoList.findIndex((listItem) => listItem === item);
    
      const editItemText = ({ target: { value } }) => {
        const newList = replaceItemAtIndex(todoList, index, {
          ...item,
          text: value,
        });
        setTodoList(newList);
      };
    
      return (
        <div>
          <input type='text' value={item.text} onChange={editItemText} />
          <input />
          <button>X</button>
        </div>
      );
    };
    
    const replaceItemAtIndex = (todoList, index, newValue) => {
      return [...todoList.slice(0, index), newValue, ...todoList.slice(index + 1)];
    };
    };

     

     

     

     

     

     

     

    useRecoilValue

    : Recoil state값을 반환한다. (읽기)

    const count = useRecoilValue(countState);

     

    [활용]

    import React from 'react';
    import { useRecoilValue } from 'recoil';
    import { todoListState } from '../recoil';
    import { TodoItem } from './TodoItem';
    import { TodoitemCreator } from './TodoitemCreator';
    
    export const TodoList = () => {
      const todoList = useRecoilValue(todoListState);
      return (
        <>
          <TodoitemCreator />
          {todoList.map((item) => (
            <TodoItem key={item.id} item={item} />
          ))}
        </>
      );
    };

     

     

     

     

     

     

     

     

     

     

    useSetRecoilState

    : 내용을 업데이트하는 setter 함수에 접근한다. (쓰기)

     
    const setCount = useSetRecoilState(countState);
    import React, { useState } from 'react';
    import { useSetRecoilState } from 'recoil';
    import { todoListState } from '../recoil';
    
    export const TodoitemCreator = () => {
      const [inputValue, setInputValue] = useState('');
      const setTodoList = useSetRecoilState(todoListState);
    
      const handleInputChange = ({ target: { value } }) => {
        setInputValue(value);
      };
    
      const addItem = () => {
        setTodoList((oldList) => [
          ...oldList,
          {
            id: getId(),
            text: inputValue,
            inComplete: false,
          },
        ]);
      };
    
      return (
        <div>
          <input type='text' value={inputValue} onChange={handleInputChange} />
          <button onClick={addItem}>Add</button>
        </div>
      );
    };
    
    let id = 0;
    function getId() {
      return id++;
    }

     

     

     

     

     

     

    useResetRecoilState

    : atom이나 selector의 값을 초기화

    const resetCount = useResetRecoilState(countState);
    ...
    <button onClick={resetCount}>reset count</button>

     

     

     

     

     

     

     

     

     

     

     

     
    반응형