커스텀 훅

노성호·2021년 7월 28일
0

react

목록 보기
11/12

비동기 리퀘스트를 위한 커스텀 훅을 만들어서 사용해봤다.

useEffect(() => {
  async function getRequest(id: number) {
    await axios...expresion
  }
  
  setState(getRequest(id));
  
}, [])

뭐 대충 이렇게 짰던것 같다. 리스트를 렌더링하려고 구현했는데, 리스폰스 받는데 시간이 조금 걸리면 리스트가 제대로 렌더링되지 않는 문제가 발생했다. 그래서 리액트 공식문서를 보다가 커스텀 훅을 이용해 해결할수 있지 않을까 싶었다.

function getSome(someId: number) {
  const [someValues, setSomeValues] = useState<
    {
      id: number;
      title: string;
      public: boolean;
    }[]
  >([]);

  async function asyncGetSomes(id: number) {
    await axios
      .get(`/some/${id}`)
      .then((response) => {
        setSomeValues(response.data.someArr);
      })
      .catch((e) => console.log(e));
  }

  useEffect(() => {
    asyncGetSomes(someId);
  }, []);

  return someValues;
}

커스텀 훅

커스텀 훅은 위와같이 구현했다.

function Component(someId: number) {
  const someArray = getSome(someId)
  
  const someList = someArray.map((item, index) => {
    return (
      <SomeItem
        id={item.id}
        title={item.title}
        public={item.public}
        key={index}
      />
    );
  });
}

컴포넌트 내 리스트는 이렇게 구현했다.
이렇게 구현하니 리스폰스 받는 시점과 리스트를 렌더링하는 시점의 차이가나지 않아서 리스트가 제대로 렌더링 되었다. 아마도 someArray 변수에 비동기 할당이 일어나기 때문에 렌더링 시점까지 기다렸다가 리스트를 생성하는게 아닐까 생각되는데, 정확한 구현원리는 다음에 알아보겠다(당장은 일을 해야한다)

그런데, 리퀘스트를 만들때마다 커스텀 훅을 만드니 이게 여간 귀찮은게 아니다. 이걸 더 제네릭하게 만들수 있는 방법이 없을까 해서 찾아보고 질문하고 하다보니 답을 찾았다. 사실 문제해결을 위한 키워드는 알고 있었는데 질문을 통해 알아내서 좀 그렇긴 하다.

function getSomeArray<T>(url: string, initialValue: T[], propsType: string) {
  const [someValues, setSomeValues] = useState<T[]>(initialValue);

  async function asyncGetSomes() {
    await axios
      .get(url)
      .then((response) => {
        const resultArray = response.data[propsType].map((item) => return item }
        setSomeValues(response.data.someArr);
      })
      .catch((e) => console.log(e));
  }

  useEffect(() => {
    asyncGetSomes();
  }, []);

  return someValues;
}

요렇게 제네릭으로 구현하면 됨. asyncGetSome 함수의 파라메터에 url과 setSomeValues를 넣어준다면 좀 더 함수형 프로그래밍스럽게 구현 될 것 같다.

propsType: string으로 리스폰스의 프로퍼티 타입은 해결.

function Component(){
  const someArray = getSomeArray(url, [], 'propsType');
  
  const lists = someArray.map((item) => <AnotherItem {...item} />);
}

컴포넌트는 위와같이 구현했다. 사실 처음 구현한것과 다른건 없다. 커스텀훅의 매개에 props를 넣고 리턴값을 tsx(jsx)로 바꾸면 개별 컴포넌트에서 비동기 리퀘스트를 보내는 컴포넌트가 된다. 큰 차이는 없지만 재사용 / 컴포넌트에 직접 구현에 따라 달리 사용하면 될 것 같다.
하지만 어떤것이 베스트 프랙티스인지는 아직 잘 모르겠다.

0개의 댓글