실전프로젝트 TIL21일차(7/14)

임준수·2022년 7월 15일
0

프론트 깃허브 링크
실전프로젝트 SA링크

실전 프로젝트에서는 원래 배운 내용들을 깃허브에 올리는 방식이 아닌 하루하루 진행 상황과 느낀점들을 기록하기 위해서 벨로그에 TIL을 작성하기로 했다.

1. 진행상황

로그인 관련 기능 구현중

마이페이지 기능 구현중

2. 배운 내용들

1. Recoil 세팅하기

index.tsx에 app을 로 감싸준다.

import { RecoilRoot } from "recoil";
  
  
 const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement
);
root.render(
  <BrowserRouter>
    <RecoilRoot>
        <App />
    </RecoilRoot>
  </BrowserRouter>
);

reportWebVitals();
  

2. Atom파일에 atom 만들기

고유 이름인 key와 원하는 값인 default를 넣어준다.

이때 default 값을 [] 배열로 넣으면 map을 돌릴 수 있다.

import { atom, selector } from "recoil";

export const data = atom({
key: "data",
default: [
  {
    id: 1,
    subject: "제목1",
    category: "음식"
  },
  {
    id: 2,
    subject: "제목2",
    category: "음식"
  },
  {
    id: 3,
    subject: "제목3",
    category: "스포츠"
  },
  {
    id: 4,
    subject: "제목4",
    category: "음식"
  },
]
});

3. 컴포넌트에서 꺼내쓰기

데이터 조회만(getter) 하고 싶은 경우 = RecoilValue
setter 만 쓰고 싶은 경우 = useSetRecoilState 를 사용한다.

출력할 때는 useState 쓰는 것처럼 useRecoilState를 사용, getter, setter로 사용한다.

import { useRef } from "react";
import { useRecoilState, useResetRecoilState, useSetRecoilState } from "recoil";
import { category, select } from "./atoms";

function App() {
// const [list, setList] = useRecoilState(data);
// const resetTest = useResetRecoilState(data);
const [list, setList] = useRecoilState(select);
const [nowCategory, setNowCategory] = useRecoilState(category);
const ref = useRef(null);

const onClick = (e) => {
  setList(current => [...current, { id: Date.now(), subject: ref.current.value, category: nowCategory }]); // 불변성
}

const onChange = (e) => {
  setNowCategory(e.target.value);
}

return (
  <div>
    <select onChange={onChange}>
      <option value="음식">음식</option>
      <option value="스포츠">스포츠</option>
    </select>
    {list?.map((v, i) => {
      return <div key={i}>{v.subject}</div>
    })}
    <input type="text" ref={ref} />
    <button onClick={onClick}>추가</button>
  </div>
);
}

export default App;

setList로 default 값을 변경할 때는 불변성을 지켜야한다.
기존의 값을 유지해야하므로 current => ...current로 작성한다.

default 값을 원래대로 돌릴 때는 useRestRecoilState( 변수명 ); 을 사용한다.

4. Selector

Selector는 순수 함수이고 atom이나 다른 selector의 입력값으로 받는다.

이러한 상위 atom이나 selector가 업데이트 되면 selector 함수는 다시 계산될 것이다.
컴포넌트들은 atom처럼 selector를 구독할 수 있으며, selector가 변화하면 리렌더링이 일어난다.

selector는 상태에 기반하여 파생된 데이터를 계산할 때 사용된다.
최소한의 상태가 atom에 저장되어 있고 효율적으로 함수에 의해 계산되기 때문에 취약한 상태를 가지는 것을 피할 수 있다.

selector가 계속하여 어떤 컴포넌트가 필요로 하고 어떠한 상태에 그들이 의존하는지를 추적하기 때문에 이러한 함수적 접근은 매우 효율적이다.

예 ) data의 카테고리에 "음식" 만 뽑아서 보고 싶은 경우 ?
: data를 가져와서 리스트를 뿌려주는게 아니라,
selector를 가져오는 것 !

import { atom, selector } from "recoil";

export const data = atom({
key: "data",
default: [
  {
    id: 1,
    subject: "제목1",
    category: "음식"
  },
  {
    id: 2,
    subject: "제목2",
    category: "음식"
  },
  {
    id: 3,
    subject: "제목3",
    category: "스포츠"
  },
  {
    id: 4,
    subject: "제목4",
    category: "음식"
  },
]
});

export const category = atom({
key: "category",
default: "음식"
})

// 내 데이터를 원하는 형태로 가공해서 출력, 수정하고 싶을 때 사용
export const select = selector({
key: "data2",
get: ({get}) => {
  const oldList = get(data);
  const cat = get(category);
  return oldList.filter((v) => v.category === cat);
},
set: ({set}, newValue) => {
  set(data, newValue)
  console.log(newValue);
}
});

selector 함수 안에는 get함수와 set함수가 존재하고
get 함수로 기존 atom에 데이터를 받아오고, set 함수로 바꿔준다.

0개의 댓글