React 애플리케이션을 위한 상태 관리 라이브러리
💻첫 상태관리 라이브러리를 Recoil을 선택한 이유
: 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가 최신 상태를 반영하도록 보장
: 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} />;
}
: Recoil의 atom 또는 selector의 값을 읽는데 사용
➡️ 상태를 읽기 전용으로 사용하는데 유용
import { useRecoilValue } from 'recoil';
function TextDisplay() {
const text = useRecoilValue(textState);
return <div>{text}</div>;
}
: Recoil 상태를 업데이트 하는 함수만을 제공
➡️ 이 훅은 상태를 변경할 수 있지만 , 현재 상태 값을 읽을 수 없음
import { useSetRecoilState } from 'recoil';
function TextUpdater() {
const setText = useSetRecoilState(textState);
const onClick = () => {
setText('Hello, Recoil!');
};
return <button onClick={onClick}>Update Text</button>;
}
: Recoil의 atom 상태를 초기값으로 재설정하는데 사용
import { useResetRecoilState } from 'recoil';
function ResetButton() {
const resetText = useResetRecoilState(textState);
return <button onClick={resetText}>Reset</button>;
}
: 비동기 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);
}
});
});
[floating Label] 움직이는 placeholder 만들기 (0) | 2025.03.05 |
---|---|
[recoil] 그럼 Recoil은 언제 써야해요 ? (0) | 2025.02.21 |
[React-Query] React-Query가 뭔데요? (0) | 2025.02.18 |