본문 바로가기

React

React + Recoil 초기 셋팅 및 테스트

반응형

React로 개발하다보면 상태관리에 대한 고민을 안할 수가 없다. 나 또한, 상태관리에 대해 고민하던 중 회사에서 redux를 적용했는데 redux 까지는 여차저차 괜찮았으나, 추가로 redux-toolkit, redux-saga 를 적용하려고 보니, 러닝커브가 높아서 막막했다. (더 편하게 개발하라고 나온 것들이지만...) 그러던 중 작년 5월즈음에 페이스북에서 recoil 을 발표했고, 고민없이 recoil 을 적용해봤는데 React hooks 개념이고 초기셋팅도 엄청 간단해서 recoil 로 넘어와버렸다...

아직 정식 major 버전은 릴리즈를 못한 것 같다. 하지만 minor 버전은 계속 업그레이드 하고 있고, 곧 정식 릴리즈가 되지 않을까 한다.

 

일단 먼저 recoil 을 테스트하기 위한 실습 프로젝트를 CRA를 통해 생성한다.

npx create-react-app react-recoil-base
cd react-recoil-base

 

리코일 패키지를 설치한다.

yarn add recoil

※ 아직은 별다른 확장형 패키지는 없는 것 같다.

 

프로젝트의 엔트리 파일 (./index.js) 에서 RecoilRoot로 감싸준다.

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

ReactDOM.render(
    <RecoilRoot>
        <App/>
    </RecoilRoot>,
    document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals

※ RecoilRoot 로 감싸는 컴포넌트(여기서는 <App/>) 부터 리코일 객체(atom)를 사용할 수 있음을 유의한다.

 

초기 셋팅 자체는 상당히 간단하다. (redux 처럼 리듀서를 만들고 store 를 생성한 뒤 공급자에 넣어줄 필요가 없다.)

 

이 후, atom 객체를 생성한다. (./src/states/counter.js)

import { atom, selector } from 'recoil';

export const counterState = atom({
    key: 'counterState',
    default: 0
});

export const counterLabelSelector = selector({
    key: 'counterLabelSelector',
    get: ({ get }) => {
        const counter = get(counterState);
        return `현재 카운터는 ${counter} 입니다.`;
    }
});

※ atom 은 redux 의 store 와 유사한 개념으로, 상태의 단위 이다. React 에서 사용하는 state 와 같은 개념으로 atom 의 값이 변경되면, atom 을 구독하고 있는 모든 컴포넌트들이 리렌더링되고 변경된 atom 의 state 값을 사용하게 된다.

  • atom 객체는 key 와 default 두가지의 필수 값이 존재하는데 key 는 리덕스의 action type?? 과 비슷한 느낌이고, default 는 atom 초기 값 이다. (key 는 보통 atom 객체의 변수명과 같게 지정했다.) 또한, key 는 유일해야하므로 중복되면 안된다.
  • selector 객체는 read-only 한 RecoilValueReadOnly 객체로서 보통 atom 의 상태 값을 기반으로 새로운 값을 리턴할 때 사용한다. 물론 selector 는 get 을 구독하는 atom 객체가 변화하면 같이 변경된다.
  • Line 3~6 : atom 객체 생성
  • Line 8~14 : selector 객체 생성
  • Line 11 : selector 가 가져온 atom 객체

 

recoil 을 사용해서 상태값을 변경하는 컴포넌트를 생성한다. (./src/components/Counter.jsx)

import React, { useState } from 'react';
import { useRecoilState } from 'recoil';
import { counterState } from '../states/counter';

const Counter = () => {
    const [counter, setCounter] = useRecoilState(counterState);
    const [state, setState] = useState({});

    const handleChange = (evt) => {
        setState({
            ...state,
            [evt.target.name]: Number(evt.target.value)
        })
    };

    const handleClickPlus = () => {
        setCounter(counter + (state?.plus ?? 1));
    };
    const handleClickMinus = () => {
        setCounter(counter - (state?.minus ?? 1));
    };

    return (
        <div>
            <input type="text" name="plus" value={state?.plus} onChange={handleChange} />
            <button onClick={handleClickPlus}>+</button>
            <input type="text" name="minus" value={state?.minus} onChange={handleChange} />
            <button onClick={handleClickMinus}>-</button>
        </div>
    );
}

export default Counter;
  • Line 6 : useRecoilState 를 통해 counterState atom 객체를 구독한다. (방식은 useState 와 거의 동일)
  • Line 16~21 : atom 객체의 상태값을 변경하는 이벤트함수이다. (redux 의 action 함수와 유사 - dispatch 같은거 필요 없음!)

변경된 atom 객체를 렌더링 하는 소스를 작성한다. (./src/App.js)

import React from 'react';
import { useRecoilValue } from 'recoil';
import { counterState, counterLabelSelector } from './states/counter';
import Counter from './components/Counter';

function App() {
    const counter = useRecoilValue(counterState);
    const counterLabel = useRecoilValue(counterLabelSelector);

    return (
        <div>
            <Counter/>
            <div>counter : {counter}</div>
            <div>counterLabel : {counterLabel}</div>
        </div>
    );
}

export default App;
  • Line 7~8 : useRecoilValue(상태 값만을 리턴) 을 통해 atom 및 selector 객체를 구독한다.

 

 

위 화면으로 recoil 을 통한 state 변화를 확인할 수 있다.

 

recoil 에서는 위에서 사용한 hooks 말고도 더 많은 기능을 제공한다.

필요에 따라 [공식 문서]를 참고하여 적용하면 될 것으로 보인다. 

 

 

 

위 예제에 대한 샘플소스는 깃허브에 올려놓았습니다.

직접 동작해보고, atom 및 selector 객체를 만들어보면서 실습해보면 이해가 쉬울 것 입니다.

https://github.com/sbjang123456/react-recoil-base

 

sbjang123456/react-recoil-base

리액트+리코일 초기셋팅 및 연습. Contribute to sbjang123456/react-recoil-base development by creating an account on GitHub.

github.com

 

반응형