기존 리덕스의 스토어와 유사한 개념으로, 상태의 단위
atom이 업데이트 되면, 해당 atom을 구독하고 있던 모든 컴포넌트들의 state가 새로운 값으로 리렌더링 된다.
각 atom은 고유한 id인 key값으로 구분되며, 여러 컴포넌트에서 atom을 구독하고 있다면 그 컴포넌트들도 똑같은 상태를 공유한다.
atom()함수를 사용한다.
const todoListState = atom({
key: 'todoListState',
default: [],
});
이 atom에는 고유한 key와 default값을 주어야 한다.
useRecoilValue에 생성한 atom을 인자로 넣어 읽어올 수 있는 todoList를 생성해주었다.
function TodoList() {
const todoList = useRecoilValue(todoListState);
return (
<>
{/* <TodoListStats /> */}
{/* <TodoListFilters /> */}
<TodoItemCreator />
{todoList.map((todoItem) => (
<TodoItem key={todoItem.id} item={todoItem} />
))}
</>
);
}
atom인 todoListState내용을 업데이트 하기 위해서는 useSetrecoilState훅을 사용해 준다.
function TodoItemCreator() {
const [inputValue, setInputValue] = useState('');
const setTodoList = useSetRecoilState(todoListState);
const addItem = () => {
setTodoList((oldTodoList) => [
...oldTodoList,
{
id: getId(),
text: inputValue,
isComplete: false,
},
]);
setInputValue('');
};
const onChange = ({target: {value}}) => {
setInputValue(value);
};
return (
<div>
<input type="text" value={inputValue} onChange={onChange} />
<button onClick={addItem}>Add</button>
</div>
);
}
// 고유한 Id 생성을 위한 유틸리티
let id = 0;
function getId() {
return id++;
}
import * as React from 'react';
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
import { _num } from './modules/recoil/numberRecoil';
const App = (): JSX.Element => {
const [num, setNum] = useRecoilState<number>(_num); // getter와 setter를 동시에 가져올 경우
// const num = useRecoilValue<number>(_num); // getter만 가져올 경우
// const setNum = useSetRecoilState<number>(_num); // setter만 가져올 경우
const onClickIncrease = () => {
setNum(num+3); // 3만큼 증가
}
const onClickDecrease = () => {
setNum(num-2); // 2만큼 감소
}
return (
<div>
<p>현재 값: {num}</p>
<button onClick={onClickIncrease}>증가</button>
<button onClick={onClickDecrease}>감소</button>
</div>
)
}
export default App;
export const countInputState = selector({
key: 'countTitleState',
get: ({ get }) => {
return `현재 카운트는 ${get(countState)} 이고 입력값은 ${get(inputState)} 입니다.`;
},
set: ({ set }, newValue) => { // 2번째 파라미터 에는 추가로 받을 인자를 나타냅니다.
set(countState, Number(newValue)); // count atom 수정
set(inputState, newValue + ''); // input atom 수정
},
});
countInputState라는 함수를 selector로 만들었다.
import { useRecoilState } from 'recoil';
import { countState, inputState, countInputState } from '../../../recoil/count';
function SelectorCount() {
const [ count, setCount ] = useRecoilState(countState); // useRecoilState 을 통한 value, setter 반환
const [ input, setInput ] = useRecoilState(inputState); // useRecoilState 을 통한 value, setter 반환
const [ countInput, setCountInput ] = useRecoilState(countInputState);
return (
<div>
<h2>읽기 쓰기 카운트 컴포넌트</h2>
<p>카운트 {count}</p>
<p>selector {countInput}</p>
<input value={input} onChange={(e) => setInput(e.target.value)} />
<button onClick={() => setCount(count + 1)}>숫자 증가</button>
<button onClick={() => setCount(count - 1)}>숫자 감소</button>
<button onClick={() => setCountInput('9999')}>selector 값 9999로 변경</button>
</div>
);
}
export default SelectorCount;
userecoilstate에 countinputState을 넣어 countInput이라는 상태값을 만들었다.
이것은 그대로 문장으로 리턴되어 보여진다.
태값을 생성했다.
저
별도의 파일에서 달력에서 선택한 날짜를 저장하는 selectedDatesState atom을 생성했다.
//globalState.js
import { atom } from 'recoil';
export const selectedDatesState = atom({
key: 'selectedDatesState',
default: {
checkin: null,
checkout: null,
},
});
달력 컴포넌트에서는 날짜를 선택하면 선택한 날짜정보를 저장해주어야 한다. useRecoilState를 사용해 날짜정보를 저장하고 읽을 수 있도록 해준다.
//selectedDate.js
const [selectedDates, setSelectedDates] = useRecoilState(selectedDatesState);
return (
<Calendar
onSelect={(startDate, endDate, validDateRange) => {
validDate(validDateRange);
setSelectedDates({
...selectedDates,
check_in: startDate,
check_out: endDate,
});
}}
Modal에서는 검색 버튼을 눌렀을 때 달력 컴포넌트에서 선택한 날짜 값을 받아와 url에 쿼리스트링으로 넘겨주어야 하기 때문에 selectedDatesState의 값을 읽어와야한다.
useRecoilValue를 이용해 이 값을 읽어온다.
//Modal.js
const selectedDates = useRecoilValue(selectedDatesState);