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

React子组件调用父组件函数时如何获取最新父组件状态?

React状态闭包陷阱:获取最新state的解决方案

问题根源

你遇到的是典型的React闭包陷阱:onRemoveGroundLease函数在组件初次渲染时被创建,捕获了当时的process状态值。后续即使process通过setProcess更新,这个函数依然持有旧的process引用,导致打印的是原始未修改的状态。

解决方法

方法一:从子组件传递最新状态数据

子组件已经持有最新的process实例,直接让子组件调用回调时传递最新的groundLeases(或整个process),父组件无需依赖自身state,直接使用传入的最新值:

  1. 修改父组件的回调函数签名:
const onRemoveGroundLease = (groundLease: ICloserGroundLease, latestGroundLeases: ICloserGroundLease[]) => {
  console.log(latestGroundLeases); // 这里是最新的groundLeases状态
  const groundLeaseIds = latestGroundLeases?.map((gl) => gl.arkGroundLeaseId);
  
  if (groundLeaseIds) {
    const index = groundLeaseIds.indexOf(groundLease.arkGroundLeaseId);
    if (index > -1) {
      groundLeaseIds.splice(index, 1);
    }

    const payload: IProcessGroundLeaseSave = {
      processId: process.collateralCheckProcessId, // 若processId可能变化,也可让子组件传递整个process
      groundLeaseIds
    };
    
    onCommonPut({
      url: collateralCheckUrl.associateGroundLeases(),
      payload,
      successCallback: () => {
        getProcesses(process.collateralCheckProcessId);
        onCancelProcessEdit();
      }
    }, ServiceEnum.COLLATERAL_API);
  }
};
  1. 修改子组件的调用逻辑,传递最新数据:
frameworkComponents={{
  renderDeleteAction: buildDeleteActionCell({
    onDelete: (groundLease) => onRemoveGroundLease(groundLease, process.groundLeases || [])
  }),
}}

方法二:用useRef保存最新状态

通过useRef创建一个引用,每次process更新时同步最新值到ref,回调函数直接从ref获取最新状态:

  1. 父组件中添加ref和同步逻辑:
const CollateralChecks : React.FC = () => {
  const [processes, setProcesses] = React.useState<ICollateralCheckProcess[]>([]);
  const [process, setProcess] = React.useState<ICollateralCheckProcess>(null);
  // 创建ref跟踪最新process
  const processRef = React.useRef<ICollateralCheckProcess>(null);

  // 每次process更新时同步到ref
  React.useEffect(() => {
    processRef.current = process;
  }, [process]);

  // ... 其余代码
};
  1. 修改onRemoveGroundLease使用ref获取最新状态:
const onRemoveGroundLease = (groundLease: ICloserGroundLease) => {
  const latestProcess = processRef.current;
  console.log(latestProcess.groundLeases); // 最新状态
  const groundLeaseIds = latestProcess.groundLeases?.map((gl) => gl.arkGroundLeaseId);
  
  if (groundLeaseIds) {
    const index = groundLeaseIds.indexOf(groundLease.arkGroundLeaseId);
    if (index > -1) {
      groundLeaseIds.splice(index, 1);
    }

    const payload: IProcessGroundLeaseSave = {
      processId: latestProcess.collateralCheckProcessId,
      groundLeaseIds
    };
    
    onCommonPut({
      url: collateralCheckUrl.associateGroundLeases(),
      payload,
      successCallback: () => {
        getProcesses(latestProcess.collateralCheckProcessId);
        onCancelProcessEdit();
      }
    }, ServiceEnum.COLLATERAL_API);
  }
};

方法三:用useCallback确保函数捕获最新状态

将onRemoveGroundLease用useCallback包裹,并把process加入依赖数组,这样每次process更新时,函数都会重新创建,自然捕获最新的状态:

const onRemoveGroundLease = React.useCallback((groundLease: ICloserGroundLease) => {
  console.log(process.groundLeases); // 最新状态
  const groundLeaseIds = process.groundLeases?.map((gl) => gl.arkGroundLeaseId);
  
  if (groundLeaseIds) {
    const index = groundLeaseIds.indexOf(groundLease.arkGroundLeaseId);
    if (index > -1) {
      groundLeaseIds.splice(index, 1);
    }

    const payload: IProcessGroundLeaseSave = {
      processId: process.collateralCheckProcessId,
      groundLeaseIds
    };
    
    onCommonPut({
      url: collateralCheckUrl.associateGroundLeases(),
      payload,
      successCallback: () => {
        getProcesses(process.collateralCheckProcessId);
        onCancelProcessEdit();
      }
    }, ServiceEnum.COLLATERAL_API);
  }
}, [process]);

注意:这种方式会导致每次process变化时函数重新生成,可能引发子组件重渲染。如果子组件是纯组件,可以给子组件加上React.memo优化:

export default React.memo(CollateralCheckForm);

内容的提问来源于stack exchange,提问作者Conrad Addo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 12:02:15