Recoil로 상태관리하기

김범식·2023년 7월 9일
0

React

목록 보기
1/3
post-thumbnail



🍎 Recoil

공식 문서 :https://recoiljs.org/ko/docs/introduction/getting-started/

혼자서 가벼운 프로젝트를 하려고 할 때, Redux tookit과 Recoil중 어떤 상태관리 라이브러리를 사용해야 할지 정말 고민이 되었다. 둘다 많이 사용되는 유명한 라이브러리고 React 자체를 처음 사용해보는 내 입장에서는 비교적 가볍다고 여겨지는 Recoil을 사용하기로 결정했다.



⭐ Recoil 이란


Recoil이란 가볍고 간편한 전역 상태 관리 라이브러리다. React 애플리케이션에서 전역 상태를 효율적으로 관리할 수 있도록 해준다.



⭐ Recoil 설치


npm install recoil
yarn add recoil



⭐ RecoilRoot


recoil을 처음 사용한다면 recoil을 사용하는 컴포넌트는 <RecoliRoot> 이라는 부모 컴포넌트가 필요하다.

import React from 'react';
import {
  RecoilRoot,
  atom,
  selector,
  useRecoilState,
  useRecoilValue,
} from 'recoil';

function App() {
  return (
    <RecoilRoot>
      <CharacterCounter />
    </RecoilRoot>
  );
}

제일 넣기 좋은 장소는 React의 제일 상위컴포넌트인 App() 컴포넌트이다. 이곳에 위치시키면 내가 만드는 모든 컴포넌트에서 Recoil로 상태관리를 할 수 있다.



⭐ Atom


이제 상태를 관리할 시간이다. 만약 유저의 상태를 전역으로 관리하고 싶다면 다음과 같은 코드를 작성할 수 있다.

// atoms.js
import { atom } from 'recoil';

export const userState = atom({
  key: 'userState',
  default: {
		id:"",
		firstName:"",
		lastName:"",
		email:"",
		gender:"",
		age:0,	
	}
,
});
  • key : 전역 상태를 나타내는 유일한 아이디로 작성해야한다.
  • default : 기본 값



📎 useRecoilState()

컴포넌트가 atom을 읽고 쓰게 하기 위해서는 useRecoilState()를 사용하면 된다.

import React from 'react';
import { useRecoilState } from 'recoil';
import { userState } from './atoms';

function UserForm() {
  const [user, setUser] = useRecoilState(userState); //전역 상태 관리 

  const handleChange = (event) => {
    const { name, value } = event.target;
    setUser((prevUser) => ({
      ...prevUser,
      [name]: value,
    }));
  };

  return (
    <div>
      <h2>User Form</h2>
      <form>
        <label>
          ID:
          <input type="text" name="id" value={user.id} onChange={handleChange} />
        </label>
        <br />
        <label>
          firstName:
          <input type="text" name="name" value={user.name} onChange={handleChange} />
        </label>
        <br />
        <label>
          lastName:
          <input type="text" name="name" value={user.name} onChange={handleChange} />
        </label>
        <br />
        <label>
          Email:
          <input type="email" name="email" value={user.email} onChange={handleChange} />
        </label>
        <br />
        <label>
          Gender:
          <input type="text" name="gender" value={user.gender} onChange={handleChange} />
        </label>
        <br />
        <label>
          Age:
          <input type="number" name="age" value={user.age} onChange={handleChange} />
        </label>
      </form>
    </div>
  );
}
  • useRecoilState()를 사용하면 어떤 컴포넌트에서도 userState를 불러와 사용할 수 있다.



📎 useResetRecoilState()

위의 예시 코드에서는 유저정보를 담는 atom을 사용했다. 그런데 만약 로그아웃을 한다면 atom에 담긴 유저정보를 초기화 시킬 필요가 있을 것이다. 그때 사용하는 것이 useResetRecoilState() 이다.

import React from 'react';
import { useResetRecoilState } from 'recoil';
import { userState } from './atoms';

function ResetButton() {
  const resetUserState = useResetRecoilState(userState);

  const handleReset = () => {
    resetUserState();
  };

  return (
    <button onClick={handleReset}>logout</button>
  );
}
  • resetUserState 변수에 저장한 함수를 실행시키면 atom을 작성했을 때 기본값으로 작성한 default로 상태 값이 변하게 된다.



⭐ Selector


Recoil에서는 Seletor를 사용하여 파생된 상태를 계산하고 관리할 수 있다. 이게 무슨말이냐하면 다른 원자의 값을 읽어와서 내 입맛대로 바꿀 수 있다는 이야기 이다.

가령 다음과 같은 userState가 있다고 해보자

// atoms.js
import { atom } from 'recoil';

export const userState = atom({
  key: 'userState',
  default: {
		id:"",
		firstName:"",
		lastName:"",
		email:"",
		gender:"",
		age:0,	
	}
,
});

우리는 selector를 사용해서 원하는 값을 내맘 대로 가공해서 꺼낼 수 있다.

import { selector } from 'recoil';
import { userState } from './atoms';

export const fullNameSelector = selector({
  key: 'fullNameSelector',
  get: ({ get }) => {
    const user = get(userState); //useState선택
    return `${user.firstName} ${user.lastName}`; //반환
  },
});

useRecoilValue를 사용해 selector에서 값을 꺼낼 수 있다.

import React from 'react';
import { useRecoilValue } from 'recoil';
import { fullNameSelector } from './selectors';

function UserProfile() {
  const fullName = useRecoilValue(fullNameSelector);

  return (
    <div>
      <h2>User Profile</h2>
      <p>Full Name: {fullName}</p>  
    </div>
  );
}

selector에서 가공한 값을 useRecoilValue를 사용해 fullName 변수에 할당하여 사용자이름을 표시할 수 있다.

물론 selector가 의존하는 상태 원자의 값이 변경될 때마다 적절하게 업데이트된다.



⭐ Effect


atom Eeffects는 부수 효과를 관리하고 Recoil의 atom을 초기화 또는 동기화 하기 위한 API 이다.

다음은 브라우저의 localStorage와 atom을 동기화 하는 간단한 예시이다.

const localStorageEffect = key => ({setSelf, onSet}) => {
  const savedValue = localStorage.getItem(key)
  if (savedValue != null) {
    setSelf(JSON.parse(savedValue));
  }

  onSet((newValue, oldValue, isReset) => { //atom이 변경될때만 호출
    isReset
      ? localStorage.removeItem(key)
      : localStorage.setItem(key, JSON.stringify(newValue));
  });
};

const currentUserIDState = atom({
  key: 'CurrentUserID',
  default: "1",
  effects: [
    localStorageEffect('current_user'),
  ]
});
  • localStorageEffect : atom의 effects옵션에서 사용할 함수를 정의했다.
  • setSelf : atom을 생성할 때(어플리케이션 시작시), 초기값을 지정하기 위해 사용된다.
  • onSet :set함수를 통해 atom의 값이 변할 때마다 사용된다.
profile
frontend developer

0개의 댓글