TIL 22-06-25

thisisyjin·2022년 6월 25일
0

TIL 📝

목록 보기
69/113

Recoil

Recoil은 원자(atom, 공유상태) 에서 Selector(순수 함수)를 거쳐
React Components로 흐르는 데이터 흐름 그래프를 만들게 해줌.

Atom은 리액트 컴포넌트가 subscribe 할 수 있는 상태 단위이다.
Selector은 이 상태를 동기식 or 비동기식으로 변환한다.

RecoilRoot

  • Redux의 Provider 역할.

  • 여러개의 RecoilRoot가 공존할 수 있고, atom state의 독립적인 공급자를 나타낼 수 있음.

  • 컴포넌트 - recoil 연동시 해당 컴포넌트와 가장 가까이 있는 RecoilRoot를 사용함.

import {RecoilRoot} from 'recoil';

function AppRoot() {
  return (
    <RecoilRoot>
      <ComponentThatUsesRecoil />
    </RecoilRoot>
  );
}

Atom

  • Recoil에서 상태를 정의하는 방법.
import { atom } from 'recoil';

const todoListState = atom({
  key: 'todoListState',
  default: [],
});

const 상태 = atom({ }) 의 형태로 선언함.

  • 고유값인 key와 기본값인 default 를 설정하면 됨.

useRecoilState

const [todoList, setTodoList] = useRecoilState(todoListState);

useRecoilState()는 useState처럼 배열을 반환한다.
인자로는 atom의 key를 적어준다.

구조분해 할당으로 1) state, 2) setState 를 선언해준다.

setState의 경우에는 setTodoList(todo)와 같이 값을 넣어주면 된다.
(useState 쓰듯이)

todoListsetTodoList는 아래와 같이 각각 선언해줄 수 있다.

useRecoilValue

const todoList = useRecoilValue(todoListState);

useSetRecoilState

const setTodoList = useSetRecoilState(todoListState);

Example

Todo List 예제 (cr: https://recoiljs.org/docs/basic-tutorial/atoms)

  1. TodoList
function TodoList() {
  const todoList = useRecoilValue(todoListState);

  return (
    <>
      {/* <TodoListStats /> */}
      {/* <TodoListFilters /> */}
      <TodoItemCreator />

      {todoList.map((todoItem) => (
        <TodoItem key={todoItem.id} item={todoItem} />
      ))}
    </>
  );
}
  1. TodoItemCreator
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++;
}
  1. TodoItem
    -> todoList(state)를 item이라는 props로 전달받음
function TodoItem({item}) {
  const [todoList, setTodoList] = useRecoilState(todoListState);
  // 🔺 todoList를 가져오고, setTodoList도 선언함
  const index = todoList.findIndex(listItem => listItem === item);
  // 인덱스를 찾아옴
 

  const editItemText = ({target: {value}}) => {
    const newList = replaceItemAtIndex(todoList, index, {
      ...item,
      text: value,
    });
    setTodoList(newList);
  };

  const toggleItemCompletion = () => {
    const newList = replaceItemAtIndex(todoList, index, {
      ...item,
      isComplete: !item.isComplete,
    });
    setTodoList(newList);
  };

  const deleteItem = () => {
    const newList = removeItemAtIndex(todoList, index);
    setTodoList(newList);
  };

  return (
    <div>
      <input type="text" value={item.text} onChange={editItemText} />
      <input
        type="checkbox"
        checked={item.isComplete}
        onChange={toggleItemCompletion}
      />
      <button onClick={deleteItem}>X</button>
    </div>
  );
}

function replaceItemAtIndex(arr, index, newValue) {
  return [...arr.slice(0, index), newValue, ...arr.slice(index + 1)];
}
// ex> i번째 아이템을 수정하려면?
// [1,2,3,4,5].slice(0, i)
) , newValue , ...[1,2,3,4,5].slice(i+1)]

function removeItemAtIndex(arr, index) {
  return [...arr.slice(0, index), ...arr.slice(index + 1)];
}
// ex> i번째 아이템을 제거하려면?
// [1,2,3,4,5].slice(0, i), ... [1,2,3,4,5].slice(0, i+1)

🔻 TIP - 배열 특정 인덱스 값 변경

![](https://velog.velcdn.com/images/thisisyjin/post/83f17608-20f9-4047-9794-5b029312d904/image.png


Selector

profile
기억은 한계가 있지만, 기록은 한계가 없다.

0개의 댓글