React自定义hook传入空对象触发无限重渲染,有没有更优解决办法?
问题复现
自定义Hook代码
export function myHook<TVariables = Record<string,string>> (variables?: TVariables) { const [result, setResult] = useState<number>(); const fooFunction = (variables?: TVariables) => { // 实际业务中会对variables做对应处理 setResult(666); } useEffect(() => { fooFunction(variables); }, [variables]) return result; }
组件调用代码
export interface IMyVariables { // 此处为空接口,仅为示例使用 } const MyComponent: React.FunctionComponent = () => { const variables = {}; const result = myHook<IMyVariables>(variables); return <></>; }
问题说明
组件每次渲染都会生成新的空对象引用,React对useEffect依赖做浅比较时会判定variables发生变更,触发「执行effect→更新state→组件重渲染」的无限循环。
目前可行的临时方案是用useMemo缓存空对象保证引用稳定:const params = useMemo(() => { return {}; }, []);
更优雅的解决方案
以下三个方案均可解决问题,可根据实际业务场景选择:
- 方案1:Hook内部设置默认值兜底
将空对象常量提到Hook外部作为默认入参,外部无参数时直接不传值即可,无需额外处理引用:
组件调用简化为:// 常量定义在Hook外部,全局唯一稳定引用 const EMPTY_OBJECT = {} as const; export function myHook<TVariables = Record<string,string>> (variables: TVariables = EMPTY_OBJECT as TVariables) { // 原有逻辑不变 const [result, setResult] = useState<number>(); const fooFunction = (variables?: TVariables) => { setResult(666); } useEffect(() => { fooFunction(variables); }, [variables]) return result; }const result = myHook<IMyVariables>() - 方案2:使用深度比较的useEffect
若业务中经常需要传入对象类型依赖,可将Hook内的原生useEffect替换为深度比较版本,直接对比对象内容而非引用:// 仅替换useEffect即可,外部调用无需修改 useDeepCompareEffect(() => { fooFunction(variables); }, [variables]) - 方案3:抽离全局稳定常量
若不想修改Hook内部逻辑,可将常用的空对象、空数组抽成全局公共常量,组件直接引用即可保证引用稳定:
组件内调用:// 全局常量文件定义 export const EMPTY_OBJ = {} as const; export const EMPTY_ARR = [] as const;const variables = EMPTY_OBJ as IMyVariables
内容的提问来源于stack exchange,提问作者jeancallisti
相关产品推荐
相关产品推荐

