본문 바로가기

클라이언트/React
[리액트(React)] 리코일(Recoil)

// 리코일, Recoil

- React 앱의 상태 관리(state management)를 위한 라이브러리

- 전역 상태 관리 라이브러리

- React의 기본 원리를 적용하고 있어서 구성이 용이하다.

- Redux보다 더 간단하게 사용할 수 있다.

- 가장 작은 단위인 atom을 생성하여 값을 저장한 후, 그 값이 필요한 component와 atom을 연결하여 값을 가져올 수 있다.


1. 설치

npm install recoil

2. index.tsx 파일 설정하기

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement,
);
root.render(
  <React.StrictMode>
    <RecoilRoot>
      <QueryClientProvider client={queryClient}>
        <App />
      </QueryClientProvider>
    </RecoilRoot>
  </React.StrictMode>,

- <RecoilRoot > 컴포넌트로 감싼다.


// Atom

- Recoil 상태 관리의 단위

- 고유한 key를 가지고 상태를 관리한다.

- 컴포넌트에서 직접 상태를 읽고 수정할 수 있다.


▪ atom 생성하기

import { atom } from 'recoil';

export const 변수명 = atom({
  key: '고유값',
  default: 기본값,
});

▪  atom에서 값 받아오기

import { useRecoilValue } from 'recoil';

const 변수명 = useRecoilValue(atom 변수명);

▪  atom에서 값 변경하기

import { useSetRecoilState } from 'recoil';

const setter함수명 = useSetRecoilState(atom명);

() => setter함수명(() => 변경할값)

▪  값 받아오기 + 변경하기

import { useRecoilState } from 'recoil';

const [값, setter함수] = useRecoilState(atom변수명);

 


import React from 'react';
import styled from 'styled-components';
import { Link } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import { fetchCoins } from '../api';
import { Helmet } from 'react-helmet';
import { useSetRecoilState } from 'recoil';
import { isDarkAtom } from '../atoms';

interface ICoin {
  id: string;
  name: string;
  symbol: string;
  rank: number;
  is_new: boolean;
  is_active: boolean;
  type: string;
}

function Coins() {
  const setDarkAtom = useSetRecoilState(isDarkAtom);
  const toggleDarkAtom = () => setDarkAtom((prev) => !prev);
  const { data, isLoading } = useQuery<ICoin[]>({
    queryKey: ['allCoins'],
    queryFn: fetchCoins,
  });

  return (
    <Container>
      <Helmet>
        <title>코인</title>
      </Helmet>
      <Header>
        <Title>코인</Title>
        <button onClick={toggleDarkAtom}>Toggle Mode</button>
      </Header>
      {isLoading ? (
        <Loader>Loading...</Loader>
      ) : (
        <CoinList>
          {data?.slice(0, 100).map((coin) => (
            <Coin key={coin.id}>
              <Link to={`/${coin.id}`} state={{ name: coin.name }}>
                <Img
                  src={`https://cryptocurrencyliveprices.com/img/${coin.id}.png`}
                  alt="coin-image"
                />
                {coin.name} &rarr;
              </Link>
            </Coin>
          ))}
        </CoinList>
      )}
    </Container>
  );
}

export default Coins;

 

import { atom } from 'recoil';

export const isDarkAtom = atom({
  key: 'isDark',
  default: false,
});

// selector

- atom을 변환된 상태로 출력하는 함수

- derived state


▪ selector 생성하기

import { selector } from 'recoil';

const selector변수명 = selector({
  key: '식별자명',
  get: ({ get }) => {
    const 변수명 = get(atom 변수명);
    //atom 값 처리
    return ;
  },
  set: ({ set }, newValue) => {
    set(atom 변수명, newValue);
  },
});

▪ selector 통해 값 받아오기

import { useRecoilValue } from 'recoil';

const 변수명 = useRecoilValue(selector변수명);

▪ selector 통해 값 수정하기

import { useRecoilValue } from 'recoil';

const [value변수명, setter함수명] = useRecoilState(selector변수명);
setter함수명(값);

import { useRecoilValue } from 'recoil';
import { toDoSelector } from './atoms';
import CreateToDo from './CreateToDo';
import Todo from './Todo';

function ToDoList() {
  const [toDo, doing, done] = useRecoilValue(toDoSelector);
  return (
    <div>
      <h1>To Dos</h1>
      <hr />
      <CreateToDo />
      <h2>To Do</h2>
      <ul>
        {toDo.map((toDo) => (
          <Todo key={toDo.id} {...toDo}></Todo>
        ))}
      </ul>
      <hr />
      <h2>Doing</h2>
      <ul>
        {doing.map((toDo) => (
          <Todo key={toDo.id} {...toDo}></Todo>
        ))}
      </ul>
      <hr />
      <h2>Done</h2>
      <ul>
        {done.map((toDo) => (
          <Todo key={toDo.id} {...toDo}></Todo>
        ))}
      </ul>
    </div>
  );
}

export default ToDoList;

 

import { atom, selector } from 'recoil';

export interface IToDo {
  text: string;
  id: number;
  category: 'TO_DO' | 'DOING' | 'DONE';
}

export const toDoState = atom<IToDo[]>({
  key: 'toDo',
  default: [],
});

export const toDoSelector = selector({
  key: 'toDoSelector',
  get: ({ get }) => {
    const toDos = get(toDoState);
    return [
      toDos.filter((toDo) => toDo.category === 'TO_DO'),
      toDos.filter((toDo) => toDo.category === 'DOING'),
      toDos.filter((toDo) => toDo.category === 'DONE'),
    ];
  },
});

※ 현재 많은 Recoil 유저들이 이탈하고 있는 상황이다.

사용이 매우 용이하다는 장점이 있긴 하지만, 잘 생각하여 사용하길...

참고: https://medium.com/@clockclcok/recoil-%EC%9D%B4%EC%A0%9C%EB%8A%94-%EB%96%A0%EB%82%98-%EB%B3%B4%EB%82%BC-%EC%8B%9C%EA%B0%84%EC%9D%B4%EB%8B%A4-ff2c8674cdd5

 

Recoil, 이제는 떠나 보낼 시간이다

개요

medium.com