정말정말 어려운 문제였다 ㅠㅠ 무한스크롤로 데이터를 n페이지까지 불러온 상태에서 필터링을 하면 1페이지 데이터를 기준으로 필터링된 결과가 나오는 문제점이 있었다. 체크박스를 클릭하면서 나도 모르게 스크롤 바가 이동했고, 그에 따라 스크롤 이벤트를 감지하는 이벤트핸들러가 발동하였다.

어찌 복잡하게 얽혔던지, n페이지까지 불러온 데이터들도 1페이지 데이터 목록으로만 초기화되는 현상이 발생했다. ㅠㅠ

나는 이전 스크롤 값과 현재 스크롤 위치를 비교해서 겨우 해결했지만, 좀 더 나은 방법이 없을까 고민했었다. 그러던 중 같이 작업하시던 분께서 이 훅을 소개해주셨다.

https://react-hook-form.com/api/useform/watch/

내가 원하는 값이 변경될 때만 특정 함수가 발동되도록 설정할 수 있단 점에서 deps array와 하는 역할이 비슷했다.

import React from "react";
import { useForm } from "react-hook-form";

function App() {
  const { register, watch, formState: { errors }, handleSubmit } = useForm();
  const watchShowAge = watch("showAge", false); // you can supply default value as second argument
  const watchAllFields = watch(); // when pass nothing as argument, you are watching everything
  const watchFields = watch(["showAge", "number"]); // you can also target specific fields by their names

  // Callback version of watch.  It's your responsibility to unsubscribe when done.
  React.useEffect(() => {
    const subscription = watch((value, { name, type }) => console.log(value, name, type));
    return () => subscription.unsubscribe();
  }, [watch]);

  const onSubmit = data => console.log(data);

  return (
    <>
      <form onSubmit={handleSubmit(onSubmit)}>
        <input type="checkbox" {...register("showAge")} />
        
        {/* based on yes selection to display Age Input*/}
        {watchShowAge && <input type="number" {...register("age", { min: 50 })} />}
        
        <input type="submit" />
      </form>
    </>
  );
}

아래는 실제 사례인데, 달력 날짜 필터 조건과 페이징 조건에 따라 데이터 불러올떄의 문제였다

우선 다음과 같이 2개의 useEffect을 사용해서 각각의 상태별로 의존성 배열을 지정해주었다.

이렇게 하여야 의존성 배열에 없는 다른 상태값이 고정된다.

useEffect(() => {
    let queryString = `date=${dayjs(startDate).format(
      'YYYYMMDD',
    )}&page=${page}`;
    api
      .getReservations(queryString)
      .then(res => {
        setIsFirstPageLoading(false);
        setRenderValue(renderValue.concat(res.data));
      })
      .catch(err => {
        util.onErrorCallback(err);
      });
  }, [page]);

  useEffect(() => {
    let queryString = `date=${dayjs(startDate).format(
      'YYYYMMDD',
    )}&page=${page}`;
    api
      .getReservations(queryString)
      .then(res => {
        setIsFirstPageLoading(false);
        setRenderValue(res.data);
      })
      .catch(err => {
        util.onErrorCallback(err);
      });
  }, [startDate]);

사용자가 스크롤을 밑바닥까지 내리게 되면 page가 1 증가하고 이에 따라 첫번쨰에 있는 useEffect이 실행된다. 그리고 그에 해당하는 함수만 실행된다. 이 함수 안에는 날짜 세팅 함수가 없으므로 날짜 상태는 변하지 않게된다.