상세 컨텐츠

본문 제목

[Recoil]상태 관리 라이브러리 도전기

본문

Recoil이란? 

React 애플리케이션을 위한 상태 관리 라이브러리 

💻첫 상태관리 라이브러리를 Recoil을 선택한 이유
 : react랑 가장 사용법이 비슷해서 러닝커브가 제일 적어서 선택

작고 React스러운

: recoil이 React의 주요 철학인 선언적 UI, 컴포넌트 중심의 설계, 그리고 훅스를 사용하는 방식을 기반

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

const textState = atom({
  key: 'textState', 
  default: '', 
});

function TextInput() {
  const [text, setText] = useRecoilState(textState); 

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

  return <input type="text" value={text} onChange={onChange} />;
}

*textState
 : 전역적으로 공유되는 상태(atom) 
**TextInput 컴포넌트
 : 이 상태를 사용하며 데이터를 렌더링 , 업데이트 

***useRecoilState
: useState 훅스를 사용하는 것과 유사하게 상태관리

 

간결함과 효율성

➡️ Recoil은 상태 관리를 위한 최소한의 API만을 제공함

import { selector } from 'recoil';

const charCountState = selector({
  key: 'charCountState',
  get: ({ get }) => {
    const text = get(textState);
    return text.length;
  },
});

function CharacterCount() {
  const count = useRecoilValue(charCountState);

  return <>Character Count: {count}</>;
}

*selector
 : Atom에서의 파생 상태를 생성하기 위한 간결하고 강력한 방법
**CharaterCounter 컴포넌트
 : textState의 변경에 의존하는 파생상태 , 즉 textState의 값이 변경될 때만 재계산됨 

데이터 흐름 그래프

: 서비스의 상태와 그 상태에 의존하는 파생 데이터 간의 관계를 나타냄
➡️ 데이터의 흐름과 업데이트를 명확하게 관리하고 감시할 수 있음 

: 각 Atom은 그래프의 노드로 Selector는 Atom 노드에 의존하는 다른 노드로 표현
1️⃣ Atom의 상태가 변경되면 의존하는 모든 Selector에 전파

2️⃣ Selector는 Atom의 새로운 상태를 기반으로 다시 계산 + 관련 컴포넌트 업데이트

+) Atom의 상태가 변경되어도 해당 selector에 영향을 주지 않는 변경의 경우 Selector 재계산 X 

const textState = atom({
  key: 'textState',
  default: '',
});
const charCountState = selector({
  key: 'charCountState',
  get: ({ get }) => {
    const text = get(textState);
    return text.length;
  },
});

*selector
: textState Atom에 의존 
**charCountState 컴포넌트
 : 사용자가 텍스트를 입력할 때 마다 textState의 상태가 변경되고 charCountState는 이 변경을 감지하여 문자 수 다시 계산

//컴포넌트에서의 상호작용
function TextInput() {
//textState atom을 구족하고 상태 변경 시 재렌더링
  const [text, setText] = useRecoilState(textState);
  // ... 입력 처리 로직
  return <InputArea value={text} onChange(setText)>
} // 여기서 TextInput은 text를 구독
 
function CharacterCount() {
  const count = useRecoilValue(charCountState);
  // ... 문자 수 표시 로직
  return <div>{count}</div>
}

구독

: atom(- 애플리케이션 상태) 또는 selector(-파생데이터)의 변경을 감지하고 이러한 변경에 반응 
1️⃣ atom 또는 selector의 상태가 변경

2️⃣ 이 상태를 구독하고 잇는 모든 컴포넌트에 알림

3️⃣ 상태를 구독하는 컴포넌트들이 변경을 감지하고 이에 따라 ReRendering

       ➡️ 상태가 변경할 때마다 UI가 최신 상태를 반영하도록 보장

useRecoilState

: Recoil의 atom에 저장된 상태를 읽고 쓰는데 사용

import { atom, useRecoilState } from 'recoil';

const textState = atom({
  key: 'textState', // 고유키
  default: '', // 초기값
});

function TextInput() {
  const [text, setText] = useRecoilState(textState);

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

  return <input type="text" value={text} onChange={onChange} />;
}

 

useRecoilValue

: Recoil의 atom 또는 selector의 값을 읽는데 사용 
    ➡️ 상태를 읽기 전용으로 사용하는데 유용

import { useRecoilValue } from 'recoil';

function TextDisplay() {
  const text = useRecoilValue(textState);

  return <div>{text}</div>;
}

 

useSetRecoilState

: Recoil 상태를 업데이트 하는 함수만을 제공
    ➡️ 이 훅은 상태를 변경할 수 있지만 , 현재 상태 값을 읽을 수 없음

import { useSetRecoilState } from 'recoil';

function TextUpdater() {
  const setText = useSetRecoilState(textState);

  const onClick = () => {
    setText('Hello, Recoil!');
  };

  return <button onClick={onClick}>Update Text</button>;
}

 

useResetRecoilState

 : Recoil의 atom 상태를 초기값으로 재설정하는데 사용

import { useResetRecoilState } from 'recoil';

function ResetButton() {
  const resetText = useResetRecoilState(textState);

  return <button onClick={resetText}>Reset</button>;
}

 

useRecoilValueLoadable

: 비동기 selector의 상태를 관리하는데 사용 / 데이터의 로딩, 에러, 완료 상태를 쉽게 처리 가능

import { selector, useRecoilValueLoadable } from 'recoil';

// 비동기 Selector 정의
const asyncDataState = selector({
  key: 'asyncDataState',
  get: async () => {
    const response = await fetch('https://api.example.com/data');
    return response.json();
  },
});

function AsyncDataComponent() {
  const loadable = useRecoilValueLoadable(asyncDataState);

  switch (loadable.state) {
    case 'hasValue':
      return <div>{loadable.contents}</div>;
    case 'loading':
      return <div>Loading...</div>;
    case 'hasError':
      return <div>Error: {loadable.contents.message}</div>;
  }
}

교차하는 앱 관찰

: Recoil에서 제공하는 고급 기능
: 기본적으로 서비스 내부의 상세한 상태 변화를 체크해 가며 모두 확인할 수 있는 관찰 기능 제공

➡️ 모든 부분에서 일어나는 상태 변화를 실시간으로 정확히 파악 + 필요한 반응 취할 수있게 함
       ▫️ 상태 변화를 관찰함으로써 개발자는 애플리케이션의 지속성 관리 / 라우팅 로직 구현 / 복잡한 디버깅 기능 손쉽게 구현 가능

useRecoilTransactionObserver_UNSTABLE(({ snapshot }) => {
  snapshot.getNodes_UNSTABLE({isModified: true}).forEach(modifiedNode => {
    const atomLoadable = snapshot.getLoadable(modifiedNode);
    if (atomLoadable.state === 'hasValue') {
      console.log(`Atom ${modifiedNode.key}의 새로운 값: `, atomLoadable.contents);
    }
  });
});

관련글 더보기