React

[React] 리액트 recoil 예제 만들어 사용해보기

solfa 2024. 2. 18. 18:47

이어지는 글

https://5ffthewall.tistory.com/72

 

[React] recoil로 전역 상태 관리하기

https://5ffthewall.tistory.com/71 [React] 리액트 context API의 리렌더링 방지를 통한 성능 최적화 하기 / useMemo 사용하기 https://5ffthewall.tistory.com/67 [React] 리액트 context API로 상태 관리 하기 Context API란? Context

5ffthewall.tistory.com

 

recoil의 개념을 담은 글이다! 개념에서 더 나아가 간단한 예제를 만들어 사용법에 익숙해지고자 한다.


Recoil을 사용하여 간단한 할 일 목록 애플리케이션 만들기

 

0. 예제 파일 생성

npm create-react-app (파일 이름)

create-react-app으로 예제 앱을 생성해준다.

 

 

1. recoil 모듈 설치

npm install recoil
yarn add recoil

둘 중 하나로 모듈을 설치해준다.

다음과 같이 json파일에 recoil 버전이 나오면 잘 설치가 된 것이다! 고고

 

2. atom.js 만들기

import { atom } from 'recoil';

export const todoListState = atom({
  key: 'todoListState', // 아톰의 고유 식별자
  default: [], // 기본값은 빈 배열
});

할 일 목록을 담을 atom을 만들어준다.

 

3. selector.js 만들기

import { selector } from 'recoil';
import { todoListState } from './atom';

export const completedTodoCountState = selector({
  key: 'completedTodoCountState',
  get: ({ get }) => {
    const todoList = get(todoListState);
    return todoList.filter((todo) => todo.completed).length;
  },
});

완료된 할 일 수를 계산하는 selector을 만들어준다. 배열 길이로 할 일 수를 계산함!

get을 통해  todoListState 아톰의 값을 가져오고 완료된 할 일 수를 반환한다.

 

4. counter.jsx 만들기

import React from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { todoListState } from './atom';
import { completedTodoCountState } from './selector';

export default function Counter(){
    const [todoList, setTodoList] = useRecoilState(todoListState);
    const completedTodoCount = useRecoilValue(completedTodoCountState);

    const addItem = () => {
        setTodoList([...todoList, { text: `할 일 ${todoList.length + 1}`, completed: false }]);
      };
    
      const toggleItemCompletion = (index) => {
        const newList = [...todoList];
        newList[index] = { ...newList[index], completed: !newList[index].completed };
        setTodoList(newList);
      };

      return(
        <div>
      <h1>할 일 목록</h1>
      <button onClick={addItem}>할 일 추가</button>
      <p>완료된 할 일 수: {completedTodoCount}</p>
      <ul>
        {todoList.map((todo, index) => (
          <li key={index} onClick={() => toggleItemCompletion(index)} style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>
            {todo.text}
          </li>
        ))}
      </ul>
    </div>
      );
}

- useRecoilState()를 사용하여 구독해서 값을 불러온다! todoListState는 atom에서 정의함

  todoList 변수에는 현재 할 일 목록이 저장되고 setTodoList 함수를 통해 이 목록을 업데이트할 수 있음

 

- useRecoilValue()를 사용해 selector 값을 읽어온다! completedTodoCountState는 selector에서 정의함

  completedTodoCount 변수는 완료된 할 일의 수가 저장 됨!

 

- addItem()함수 : 할 일 목록에 새 항목을 추가한다! 할 일 목록은 아까 atom에서 불러왔음

 

- toggleItemCompletion()함수 : 완료 여부 표시!

   index를 인자로 받아 할 일 목록에서 해당하는 인덱스의 항목의 완료 여부를 변경함!

newList[index] = { ...newList[index], completed: !newList[index].completed };

   index를 인자로 받아 할 일 목록에서 해당하는 인덱스의 항목의 완료 여부를 변경함!   

   해당 항목의 completed 속성을 반전 시켜 완료 여부를 변경한다

const newList = [...todoList];

   기존 목록을 복사해 새로운 배열을 생성함

setTodoList(newList);

   새로운 배열을 setTodoList에 넣어 recoil상태로 업데이트 시킴! useRecoilState로 값을 다시 써주는 것

   이를 통해 컴포넌트는 새로운 상태를 반영하고 다시 렌더링 됨

 

5. App.js 수정

import React from 'react';
import Counter from './counter';

function App() {

  return (
    <Counter/>
  );
}

export default App;

 

6. index.js 수정

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { RecoilRoot } from 'recoil';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <RecoilRoot>
    <App />
  </RecoilRoot>
);

reportWebVitals();

반드시 최상단에 RecoilRoot를 설정해야 한다! 

App.js의 상단에 설정했더니 This component must be used inside a <RecoilRoot> component. 이런 오류가 발생했다.

완전 최상단에 위치해주면 오류 해결!

 

 

+ 컴포넌트 추가하기

recoil을 쓰는 이유 자체가 컴포넌트 간 데이터 공유인데 컴포넌트가 count밖에 없어서 아쉽다는 생각이 들어서 추가로 만들었다!

 

7. TotalCount.jsx 추가하기

import React from 'react';
import { useRecoilValue } from 'recoil';
import { completedTodoCountState } from './selector';

export default function TotalCount() {
  const completedTodoCount = useRecoilValue(completedTodoCountState);

  return (
    <div>
      <p>완료된 할 일 총 수: {completedTodoCount}</p>
    </div>
  );
}

컴포넌트 간 공유가 잘 되는지 간단하게 확인하기 위해 별 기능을 추가하진 않았다!

useRecoilValue()로 selector의 값만 받아온다!

 

7-1. App.js 수정하기

import React from 'react';
import Counter from './counter';
import TotalCount from './totalCounter';

function App() {

  return (
    <>
    <Counter/>
    <TotalCount/>
    </>
  );
}

export default App;

컴포넌트 추가를 해주면~

데이터를 잘 주고 받는 것을 확인할 수 있다!!!

뿌듯하군!

사용된 코드는 깃허브를 확인하세욤

https://github.com/ssolfa/recoil-example?tab=readme-ov-file

 

GitHub - ssolfa/recoil-example: Recoil을 사용한 간단한 할 일 목록 애플리케이션

Recoil을 사용한 간단한 할 일 목록 애플리케이션. Contribute to ssolfa/recoil-example development by creating an account on GitHub.

github.com


 

이제 recoil 실전 적용하기만 하면 된다!!!

다음엔 context API로 상태 관리를 하고 있던 내 코드를 recoil로 바꿔볼 것이다!

recoil 딱 기다려~~~

 

이어지는 다음글 >> https://5ffthewall.tistory.com/74

 

[React] 리액트 context API를 recoil로 바꾸기 / 상태 관리 도구 변경하기

이어지는글 https://5ffthewall.tistory.com/73 [React] 리액트 recoil 예제 만들어 사용해보기 이어지는 글 https://5ffthewall.tistory.com/72 [React] recoil로 전역 상태 관리하기 https://5ffthewall.tistory.com/71 [React] 리액트

5ffthewall.tistory.com

 

728x90