如何在useeffect中处理其余参数和函数导致重新渲染

dag*_*da1 9 reactjs

说我有一个这样的功能:

export const usePagedGetAll = <R, Args extends any[]>(
  baseUrl: string,
  ...args: Args
) => {
  const fn = useWrappedRemoteCall(
    async () => {
      return await fetchRequest<RemoteData<R>>(url, options);
    }
  );

  useEffect(() => {
    (async () => {
      await fn.execute(...args);
    })();
  }, [args, fn, paginationInfo.skip, paginationInfo.take]);

  return fn
};
Run Code Online (Sandbox Code Playgroud)

问题是args每次都是一个新数组,因此如果它在deps数组中,则会无限重渲染。我确实希望它在元素更改时重新呈现。

fn功能也是如此,每次都是新功能,因此将导致无限重新渲染,我该怎么办。

我可以停止应用该修复程序的钩子勾兑规则

  useEffect(() => {
    (async () => {
      await fn.execute(...args);
    })();
    // eslint-disable-next-line
  }, [paginationInfo.skip, paginationInfo.take]);
Run Code Online (Sandbox Code Playgroud)

但这似乎是一个常见问题

XYS*_*ang 3

根据你的需求,我将依赖分为两部分进行分析。

  1. 参数

args是一个数组,每次都是全新的。

考虑创建一个useCustorCompareEffect. 通过自定义比较功能。effect实际上只有当指定值改变时才会触发。

编辑 useCustorCompareEffect 演示

const useCustorCompareEffect = (callback, value, compare) => {
  const prev = useRef({ init: true, value })
  useEffect(() => {
    const { current } = prev
    if (current.init) {
      callback()
      current.init = false
    } else {
      if (!compare || !compare(value, current.value)) {
        callback()
        current.value = value
      }
    }
  }, [callback, value, compare])
}

const useDemo=()=>{
  const compare = useCallback((curr, prev) => {
    // Compare functions, return comparison results, use `useCallback` to prevent triggering `effect` due to compare
  }, [])

  useCustorCompareEffect(
    () => {
      ...
    },
    [data],
    compare,
  )
}
Run Code Online (Sandbox Code Playgroud)

要将函数用作依赖项,可以将函数定义包装在 中useCallback,然后在 中定义该函数所需的依赖项useCallback


const execute = useCallback(() => {
  console.log('update')
}, [])

useEffect(() => {
  execute()
}, [execute);
Run Code Online (Sandbox Code Playgroud)

在你的情况下,你的函数是由另一个函数获得的useWrappedRemoteCall,它需要使用useCallbackexecute定义useWrappedRemoteCall然后返回。另外,如果只execute在 in 中使用useEffect,则需要提取出来execute然后execute作为依赖使用。防止触发fn中的其他数据更改effect

const useWrappedRemoteCall = () => {
  const execute = useCallback(() => {
    console.log('update')
  }, [])
  return { execute }
}
const usePagedGetAll = () => {
  const { execute } = useWrappedRemoteCall()
  useEffect(() => {
    execute()
  }, [execute])
}
Run Code Online (Sandbox Code Playgroud)

如有其他特殊情况,请告知。