yamoo9 / likelion-FEQA

질문/답변 — 프론트엔드 스쿨, 멋사
29 stars 9 forks source link

[LAB-8] 재사용되는 Recoil Selector에 관련 질문 (selector 동적 생성) #221

Closed rodwnl closed 1 year ago

rodwnl commented 1 year ago

질문 작성자

이경주

문제 상황

image UseProductList.jsx

image UseStoreList.jsx

image MakeSelector.jsx 현재 Recoil의 atom과 selector로 store와 product의 데이터를 가져오고 있습니다. 이때 isLoading과 error는 store와 product에 둘다 쓰기 때문에 재사용 가능할거라 생각해 MakeSelector.jsx로 빼놓은 상태이며 이는 atom값을 받아 key 설정을 하는 selector 입니다.

코드 실행시 image 위와 같이 정상작동하는 것 처럼 보일수도 있으나

image 실상 개발자도구로 확인시 에러가 뜨는것을 볼 수 있습니다. 현재 isLoading과 error과 중복되는 atom의 값을 쓰고 있다고 하는데 product와 store의 atom이 다른데 왜 이런 오류가 뜨는지 잘 모르겠습니다.

프로젝트 저장소 URL

https://github.com/rodwnl/SAJA-Market/tree/feature/kyoungju/home

환경 정보

yamoo9 commented 1 year ago

문제 분석

Recoil 공식 문서에서도 살펴볼 수 없는 창의적인 방법으로 selector를 사용하려 하셨군요 😅

재밌게도 @rodwnl님과 같은 고민을 했던 분(zaydek)도 있네요. Question about generating atoms/selectors 글도 참고해보세요. 😃

문제 해결

https://github.com/facebookexperimental/Recoil/issues/145#issuecomment-632999736 답변에서 이야기 되었듯 selector를 동적 생성 하려면 selectorFamily 유틸리티를 사용 해보라고 안내합니다.

그리고 그 방법대로 selectorFamily 유틸리티를 사용하면 정상적으로 오류 출력 없이 작동됩니다. 😊

image

아래 작성된 MakeSelector.jsx 코드를 참고하세요.

MakeSelector.jsx

import {selectorFamily} from "recoil";

export const makeIsLoadingSelector = selectorFamily({
  key: "makeIsLoadingSelector",
  get:
    (atom) =>
    ({get}) => {
      const value = get(atom);
      return value.length === 0;
    },
});

export const makeErrorSelector = selectorFamily({
  key: "makeErrorSelector",
  get:
    (atom) =>
    ({get}) => {
      const value = get(atom);
      if (value.length === 0) {
        return `Error fetching ${atom.key}`;
      } else {
        return null;
      }
    },
});
rodwnl commented 1 year ago

product와 stores에 각각 isloading상태와 error 상태가 필요한데 이를 selector을 사용하고 있었고 isloading과 error 상태를 하는 값이라 양쪽에 동일한 코드가 있었습니다. 그래서 이에 대해 합칠 수 있지 않을까? 해서 시도한 결과였습니다만 일반적으로 그냥 똑같은 코드라도 각각 다른 곳에 있는게 더 나은 선택이었을까요?? 창의적인 방법이라고 하셔서 일반적으로는 어떻게 하는지가 궁금합니다

그리고 처음엔 products, isloading, error 다 atom으로 뺐었는데 products에 따라 isloading과 error 가 자동업데이트 되는 거라 selector로 빼는 리팩토링도 진행했습니다. 솔직히 recoil에 대해 아직 잘 모르겠는데ㅠㅠ 이에 대해 제가 selector를 제대로 이해하고 괜찮은 판단이었는지도 궁금합니다..!!

yamoo9 commented 1 year ago

product와 stores에 각각 isloading상태와 error 상태가 필요한데 이를 selector을 사용하고 있었고 isloading과 error 상태를 하는 값이라 양쪽에 동일한 코드가 있었습니다. 그래서 이에 대해 합칠 수 있지 않을까? 해서 시도한 결과였습니다만 일반적으로 그냥 똑같은 코드라도 각각 다른 곳에 있는게 더 나은 선택이었을까요?? 창의적인 방법이라고 하셔서 일반적으로는 어떻게 하는지가 궁금합니다

그리고 처음엔 products, isloading, error 다 atom으로 뺐었는데 products에 따라 isloading과 error 가 자동업데이트 되는 거라 selector로 빼는 리팩토링도 진행했습니다. 솔직히 recoil에 대해 아직 잘 모르겠는데ㅠㅠ 이에 대해 제가 selector를 제대로 이해하고 괜찮은 판단이었는지도 궁금합니다..!!

개인적으로 반복되는 코드 작성을 줄이는 좋은 시도 였다고 생각해요. 창의적인 사고는 사물을 다른 견해로 보는 데서 시작하죠. 덕분에 재밌었어요. 😊

그리고 selector, selectorFamily를 간단하게 정리하면 아래와 같습니다. selector는 atom에 의존하는 파생 상태를 가져오거나, 전달 받은 새 값으로 atom을 업데이트 합니다. 그리고selectorFamily는 selector를 생성하는 유틸리티입니다. 🙂