Recoil_React

miin·2022년 3월 25일
0

Library

목록 보기
6/7
post-thumbnail

정의

  • 상태관리 라이브러리
//atom 함수를 사용해서 생성
const fontSizeState = atom({
    key: 'fontSizeState',
    default: 14,
})

const fontSizeLabelState = selector({
    key: 'fontSizeLabelState',
   //get속성은 계산될 함수
    get: ({get}) => {
      const fontSize = get(fontSizeState);
      const unit = 'px';
  
      return `${fontSize}${unit}`;
    },
  });

const FontButton = () => {
    const [fontSize, setFontSize] = useRecoilState(fontSizeState);
    const fontSizeLabel = useRecoilValue(fontSizeLabelState);

    return (
        <>
            <div> font Size: ${fontSizeLabel}</div>
            <button onClick={() => setFontSize((size) => size + 1)} style={{fontSize}}>
            Enter
            </button>
        </>
    );
}

부모트리에 <RecoilRoot></RecoilRoot>로 감싸준다

atoms

  • 업데이트와 구독이 가능, 공유상태, 상태의 단위
  • 고유한 키가 필요함(중복 안됨)
  • 어떤 컴포넌트에서나 읽고 쓸 수 있다
  • atom의 값을 읽는 컴포넌트들은 암묵적으로 atom을 구독한다
  • 그래서 atom에 어떤 변화가 있으면 그 atom을 구독하는 모든 컴포넌트들이 재 렌더링 된다

selecters

  • atoms 상태값을 동기 또는 비동기 방식을 통해 변환
  • atoms나 다른 selectors를 입력으로 받아들이는 순수 함수이다
  • 상위의 atoms 또는 selectors가 업데이트되면 하위의 selector 함수도 다시 실행됨
  • 컴포넌트들은 selectors를 atoms처럼 구독할 수 있으며 selectors가 변경되면 컴포넌트들도 다시 렌더링됨
  • 최소한의 상태 집합만 atoms에 저장하고 다른 모든 파생되는 데이터는 selectors에 명시한 함수를 통해 효율적으로 계산함으로써 쓸모없는 상태의 보존을 방지
  • selectors와 atoms는 동일한 인터페이스를 가지므로 서로 대체할 수 있다
  • selector 함수를 사용해 정의함
  • useRecoilValue()를 사용해서 읽을 수 있다

<RecoilRoot ...props />

initializeState?:(MutableSnapshot => void)

  • MutableSnapshot을 사용하여 <RecoilRoot>의 원자 상태를 초기화하는 옵션 함수
  • 이것은 초기 렌더링에 대한 상태를 설정하며 이후 상태 변경이나 비동기적인 초기화를 위한 것이 아니다.
  • 비동기 상태 변경에는 useSetRecoilState()또는 useRecoilCallback()과 같은 훅을 사용한다

    override?:boolean

  • 기본값은 true로 설정되어 있으며, 이 속성은 <RecoilRoot>가 다른 <RecoilRoot>와 중첩(nested)된 경우에만 상관이 있다.
  • 만약 override가 true라면, 해당 루트는 새로운 리코일범위(스코프)를 생성할 것.
  • 만약 override가 false라면, 해당 <RecoilRoot>는 단지 자식 렌더링 외에 다른 기능을 수행하지 않기 때문에, 이 루트의 자식들은 가장 가까운 조상인 RecoilRoot의 Recoil값에 엑세스 할 것

여러<RecoilRoot>를 사용하는 경우

  • <RecoilRoot>는 여러개가 같이 존재할 수 있고, 각각이 독립적인 atom상태의 providers/store이 된다.
  • atom은 각 루트에 따라 다른 값을 갖게 되는 것이다.
  • 그리고 이러한 동작은 override를 false로 지정하지 않는 한, 루트가 다른 루트에 중첩될 때(내부루트가 외부 루트를 가릴 경우)동일하게 발생 된다.

예시

function MyApp({ Component, pageProps: { ...pageProps }, authInfo }: MyAppProps) {
 const initializer = useMemo(
  () =>
    async ({ set }: MutableSnapshot) => {
      if (authInfo) {
        set(authState, authInfo)
        setTokenAxios(authInfo.access, authInfo.refresh)
      }
    },
  [authInfo],
)
return(
	<RecoilRoot initializeState={initializer}>
		 <Component {...pageProps}/>
	</RecoilRoot>
)}

check

  • app에서 선언
    -> import { RecoilRoot } from 'recoil';
    -> return 안에서 component 감싸주기
    <RecoilRoot>
        <Component {...pageProps} />
      </RecoilRoot>
      ```
  • 사용하는 컴포넌트에서 import
    -> import { useRecoilState, useResetRecoilState } from "recoil";
    -> 사용할 모듈 불러오기 import { userInfo } from "../stores/accounts";
    -> state 선언
    const [info, setInfo] = useRecoilState(userInfo);
    const resetInfo = useResetRecoilState(userInfo);

TodoList

function TodoItem({item}) {
  const [todoList, setTodoList] = useRecoilState(todoListState);
  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)];
}

function removeItemAtIndex(arr, index) {
  return [...arr.slice(0, index), ...arr.slice(index + 1)];
}

0개의 댓글