You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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]
);

核心原因

  1. 直接调用props.onValueChange时,由于HOC已将自身的onValueChange替换原props中的回调,导致触发循环调用,无限递归。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 18:25:47