본문 바로가기

React

[React] Recoil 사용법

Recoil

 

atoms(공유상태) -> selectors(순수함수) -> React컴포넌트
 

Recoil은 Context API를 기반으로 구현되어 있으며, 함수형 컴포넌트에서만 사용할 수 있다.

ContextAPI에서는 API를 사용할 컴포넌트는 반드시 Context의 공급자(Provider) 안에 있어야 한다.

-> RecoilRoot로 감싸져야 한다.

 

한 애플리케이션에서 여러 개를 사용할 수도 있고 중첩도 가능하다.

이 때 Recoil API는 가장 가까운 조상 RecoilRoot에 접근한다.

 

import logo from './logo.svg';
import './App.css';
import { RecoilRoot } from 'recoil';
import Counter from './Counter';

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

export default App;

 

 

Atom

 

Recoil의  단위 테스터이다. 스토어에 저장되고 추출되는 데이터는 모두 Atom을 기반으로 한다.

아톰은 다음과 같이 atom() 함수에 고유한 키(key)와 기본값(default)을 전달해서 작성한다.

atom이 업데이트되면 각각의 구독된 컴포넌트는 새로운 값을 변경하여 다시 렌더링 함.

 

import { atom } from 'recoil';

let countState = atom({
    key: 'counte',
    default: 0,
})

let InputState = atom({
    key: 'input',
    default: 0,
});

export { countState, InputState };

 

 

Selector

 

스토어에 저장되고 스토어에서 가져오는 데이터는 아톰 기반이지만

가공된 데이터를 받거나 데이터를 가공하여 저장하고 싶을 때는 셀렉터(selector)를 사용한다.

작성할 때는 selector 함수에 고유한 키(key)와 게터(get)와 세터(set)를 전달하여 작성한다. (게터는 필수)

 

import React from 'react';
import { selector } from 'recoil';
import { Atom, InputState } from './Atom'

const Selector = selector({
    key: 'Selector',
    get: ({ get }) => {  //계산될 함수(get인자를 통해 atoms와 다른 selectors에 접근할 수 있음)
        const inputVal = get(InputState);
        const count = get(Atom);

        return `추가된 카운트는 ${inputVal}이고, 현재 카운트는 ${count}입니다.`;
    },
});

export default Selector;

 

 

 

<전체코드>

 

App.js

 

import './App.css';
import {
  RecoilRoot,
} from 'recoil';
import Counter from './Counter';

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

export default App;

 

 

 

CharacterCounter.js

 

import React from 'react';
import { useRecoilState } from 'recoil';
import Atom from './Atom';
import Counter from './Counter';

const CharacterCounter = () => {
    return (
        <div>
            <TextInput />
            <Counter />
        </div>
    );
};

const TextInput = () => {
    const [text, setText] = useRecoilState(Atom);

    const onChange = (evnet) => {
        setText(evnet.target.value)
    };

    return (
        <div style={{ marginTop: "30px" }}>
            <input type="text" value={text} onChange={onChange} />
            <br />
            input : {text}
        </div>
    )
}

export default CharacterCounter;

 

 

 

Counter.js

 

import React from 'react';
import {
    useRecoilState,
    useRecoilValue,
    useSetRecoilState,
    useResetRecoilState
} from 'recoil';
import { countState, InputState } from './Atom';

const Counter = () => {
    const [counter, setCounter] = useRecoilState(countState); //useRecoilState을 사용하여 다른 파일에 있는 아톰을 읽을 수 있다.
    const currentCounter = useRecoilValue(countState);  // 읽기 전용
    const counterHandler = useSetRecoilState(countState);  // 값만 변경 시키기 
    const resetCount = useResetRecoilState(countState);  // 디폴트값으로 값 변경

    const currentInput = useRecoilValue(InputState);
    const inputHandlerState = useSetRecoilState(InputState);
    const resultValue = useRecoilValue(InputState);

    const plusCount = () => {
        counterHandler((pre) => pre + 1)
    }

    const minusCount = () => {
        counterHandler((pre) => pre - 1)
    }

    const inputHandler = (e) => {
        const target = e.target.value;
        inputHandlerState(target);
    }

    const submitCount = () => {
        counterHandler((pre) => pre + Number(currentInput));
    }

    return (
        <div>
            {currentCounter}
            <br />
            <button onClick={plusCount}>플러스</button>
            <button onClick={minusCount}>마이너스</button>
            <button onClick={resetCount}>리셋</button>

            <div>
                <input type="text" onChange={inputHandler} />
                <button onClick={submitCount}>입력값 더하기</button>
                <div>{resultValue}</div>
            </div>
        </div>
    );
};

export default Counter;

 

 

<참고>

반응형