배열을 useEffect 종속성 목록으로 전달하는 중
5초마다 긴 폴링으로 데이터가 몇 개 송신됩니다.또한 어레이의 1개 항목(또는 어레이 길이 자체)이 변경될 때마다 컴포넌트가 액션을 디스패치하도록 하겠습니다.어레이를 useEffect 의존관계로 전달할 때 useEffect가 무한 루프 상태가 되지 않도록 하려면 어떻게 해야 합니까?
useEffect(() => {
console.log(outcomes)
}, [outcomes])
어디에outcomes
다음과 같은 ID 배열입니다.[123, 234, 3212]
어레이 내의 아이템은 교환 또는 삭제될 수 있으므로 어레이의 총 길이는 동일할 수 있습니다.따라서 통과할 필요가 없습니다.outcomes.length
의존성이 없기 때문입니다.
outcomes
reselect의 커스텀 셀렉터에서 가져옵니다.
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])
);
라이브 데모
또 다른 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
'programing' 카테고리의 다른 글
Angular2 이벤트 유형 (0) | 2023.04.01 |
---|---|
jHipster 샘플 앱에 자체 서명된 SSL 인증서를 추가하는 방법 (0) | 2023.04.01 |
vIM에서 JSON 들여쓰기를 수정하는 방법 (0) | 2023.04.01 |
BrowserRouter와 history.push()가 있는 라우터 (0) | 2023.04.01 |
d3.contract 축의 날짜 처리 (0) | 2023.03.27 |