programing

배열을 useEffect 종속성 목록으로 전달하는 중

magicmemo 2023. 4. 1. 09:00
반응형

배열을 useEffect 종속성 목록으로 전달하는 중

5초마다 긴 폴링으로 데이터가 몇 개 송신됩니다.또한 어레이의 1개 항목(또는 어레이 길이 자체)이 변경될 때마다 컴포넌트가 액션을 디스패치하도록 하겠습니다.어레이를 useEffect 의존관계로 전달할 때 useEffect가 무한 루프 상태가 되지 않도록 하려면 어떻게 해야 합니까?

useEffect(() => {
  console.log(outcomes)
}, [outcomes])

어디에outcomes다음과 같은 ID 배열입니다.[123, 234, 3212]어레이 내의 아이템은 교환 또는 삭제될 수 있으므로 어레이의 총 길이는 동일할 수 있습니다.따라서 통과할 필요가 없습니다.outcomes.length의존성이 없기 때문입니다.

outcomesreselect의 커스텀 셀렉터에서 가져옵니다.

const getOutcomes = createSelector(
  someData,
  data => data.map(({ outcomeId }) => outcomeId)
)

합격할 수 있다JSON.stringify(outcomes)종속성 목록:

자세한 내용은 이쪽

useEffect(() => {
  console.log(outcomes)
}, [JSON.stringify(outcomes)])

사용.JSON.stringify()또는 상세 비교 방법이 비효율적일 수 있습니다.객체의 형상을 미리 알고 있으면 커스텀 등호함수의 결과에 따라 콜백을 트리거하는 자체 효과 후크를 쓸 수 있습니다.

useEffect는 의존관계 배열의 각 값이 이전 렌더링의 인스턴스와 동일한지 여부를 확인하고 둘 중 하나가 아닌 경우 콜백을 실행합니다.따라서 사용하고 싶은 데이터의 인스턴스만 유지하면 됩니다.useRef커스텀 등호도 체크가 반환된 경우에만 새로운 것을 할당합니다.false효과를 유발합니다.

function arrayEqual(a1: any[], a2: any[]) {
  if (a1.length !== a2.length) return false;
  for (let i = 0; i < a1.length; i++) {
    if (a1[i] !== a2[i]) {
      return false;
    }
  }
  return true;
}

type MaybeCleanUpFn = void | (() => void);

function useNumberArrayEffect(cb: () => MaybeCleanUpFn, deps: number[]) {
  const ref = useRef<number[]>(deps);

  if (!arrayEqual(deps, ref.current)) {
    ref.current = deps;
  }

  useEffect(cb, [ref.current]);
}

사용.

function Child({ arr }: { arr: number[] }) {
  useNumberArrayEffect(() => {
    console.log("run effect", JSON.stringify(arr));
  }, arr);

  return <pre>{JSON.stringify(arr)}</pre>;
}

한 걸음 더 나아가 커스텀 이퀄리티 기능을 수용하는 이펙트 훅을 작성함으로써 훅을 재사용할 수도 있습니다.

type MaybeCleanUpFn = void | (() => void);
type EqualityFn = (a: DependencyList, b: DependencyList) => boolean;

function useCustomEffect(
  cb: () => MaybeCleanUpFn,
  deps: DependencyList,
  equal?: EqualityFn
) {
  const ref = useRef<DependencyList>(deps);

  if (!equal || !equal(deps, ref.current)) {
    ref.current = deps;
  }

  useEffect(cb, [ref.current]);
}

사용.

useCustomEffect(
  () => {
    console.log("run custom effect", JSON.stringify(arr));
  },
  [arr],
  (a, b) => arrayEqual(a[0], b[0])
);

라이브 데모

59467758/passing-array-to-use-effect 의존성 목록 편집

또 다른 ES6 옵션은 템플릿 리터럴을 사용하여 문자열을 만드는 것입니다.와 유사하다JSON.stringify()단, 결과는 다음 중 하나로 정리되지 않습니다.[]

useEffect(() => {
  console.log(outcomes)
}, [`${outcomes}`])

어레이의 사이즈가 변경되지 않는 경우는, 다음과 같이 분산하는 방법도 있습니다.

useEffect(() => {
  console.log(outcomes)
}, [ ...outcomes ])

loi-nguyen-huynh의 답변에 대한 부록으로 eslint expective-deps 경고를 받은 모든 사용자는 먼저 문자열화된 JSON을 변수로 분리하여 해결할 수 있습니다.

const depsString = JSON.stringify(deps);
React.useEffect(() => {
    ...
}, [depsString]);

이 OSS 패키지는 당신이 설명한 문제에 정확히 대처하기 위해 작성되었습니다(천박한 것이 아니라 의존관계 배열의 값을 상세하게 비교합니다).

https://github.com/kentcdodds/use-deep-compare-effect

사용방법/API는 다음과 같습니다.useEffect을 사용하다

단, 불필요한 깊이 있는 비교로 퍼포먼스가 저하될 가능성이 있기 때문에 불필요한 장소에서는 사용하지 않도록 주의해 주십시오.

빠른 해결책이야, 비록 일종의 해킹이지만.

const [string, setString] = useState('1');

useEffect(() => {
 console.log(outcomes)
}, [string])

또한 어레이를 업데이트하면 다음과 같이 문자열을 업데이트합니다.

setString(prev => `${prev}2`)

언급URL : https://stackoverflow.com/questions/59467758/passing-array-to-useeffect-dependency-list

반응형