React Native函数组件:用HOC扩展事件处理程序如何避免栈溢出
React Native函数组件HOC扩展事件处理栈溢出问题解决
问题场景
通过高阶组件(HOC)给React Native函数组件扩展onValueChange方法时,触发栈溢出错误,推测是替换props.onValueChange后引发了无限链式调用。相关代码如下:
const [inputState, setInputState] = useState<InputState>( props.disabled === true ? "disabled" : props.value ? "enabled" : "default" ); const onValueChange = useCallback( (nextValue: boolean) => { if (nextValue !== props.value) { setInputState(props.value ? "enabled" : "default") props.onValueChange && props.onValueChange(nextValue); } }, [setInputState, props.onValueChange, props.value] );
核心原因
- 直接调用
props.onValueChange时,由于HOC已将自身的onValueChange替换原props中的回调,导致触发循环调用,无限递归。 setInputState中使用旧的props.value判断状态,可能引发状态反复切换,加剧渲染循环。
解决方案
使用useRef存储原始的onValueChange回调,确保调用的是父组件传入的原始方法而非HOC包装后的版本,同时修正状态判断逻辑:
import React, { useState, useCallback, useRef, useEffect } from 'react'; type InputState = 'disabled' | 'enabled' | 'default'; type BaseProps = { disabled?: boolean; value?: boolean; onValueChange?: (value: boolean) => void; }; const withInputState = <P extends BaseProps>(Component: React.ComponentType<P>) => { return (props: P) => { // 存储原始onValueChange,避免引用变化导致循环 const originalOnChangeRef = useRef(props.onValueChange); // 监听父组件传入的onValueChange更新,同步到ref useEffect(() => { originalOnChangeRef.current = props.onValueChange; }, [props.onValueChange]); const [inputState, setInputState] = useState<InputState>( props.disabled === true ? "disabled" : props.value ? "enabled" : "default" ); const extendedOnChange = useCallback( (nextValue: boolean) => { if (nextValue !== props.value) { // 用最新的nextValue判断状态,而非旧的props.value setInputState(nextValue ? "enabled" : "default"); // 调用原始回调,避免触发HOC的循环调用 originalOnChangeRef.current?.(nextValue); } }, [props.value] ); // 将扩展后的方法传入原组件 return <Component {...props} onValueChange={extendedOnChange} />; }; };
关键说明
useRef存储的回调引用不会随组件渲染变化,确保每次调用的都是父组件传入的原始(或最新更新的)回调,打破循环链。- 修正
setInputState的判断逻辑,使用nextValue而非props.value,因为props.value在父组件更新前仍是旧值,避免状态设置错误。 - 依赖项中移除
props.onValueChange和setInputState(setInputState是React内置的稳定函数,无需加入依赖),减少useCallback的不必要重新创建。
内容的提问来源于stack exchange,提问作者Archimedes Trajano
相关产品推荐
相关产品推荐

