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

React中如何让父组件函数等待子组件异步验证完成后执行?

解决方案:让父组件等待子组件异步验证完成后执行焦点回调

问题核心是AG Grid的onCellFocused事件会在子组件Input的onBlur触发后立即执行,但子组件的验证是异步操作,导致回调顺序不符合预期。我们可以通过状态标记+回调挂起的方式解决这个问题。

步骤1:修改子组件,添加验证状态通知回调

让子组件在验证开始和结束时通知父组件,保留原有异步验证逻辑:

import { Input } from "antd";
import axios from "axios";

const InputWrapper = ({ value, onValidationStart, onBlurComplete }) => {
  const handleValidation = async () => {
    console.log("Start validating");
    // 通知父组件:开始验证
    onValidationStart?.();
    try {
      await axios.get("https://jsonplaceholder.typicode.com/todos/1");
      console.log("Recieved data");
    } catch (error) {
      console.log(error);
    } finally {
      console.log("End validating");
      // 通知父组件:验证完成
      onBlurComplete?.();
    }
  };

  const blurHandler = async () => {
    await handleValidation();
  };

  return (
    <div>
      <Input value={value} onBlur={blurHandler} />
    </div>
  );
};

export default InputWrapper;

步骤2:父组件中管理验证状态,挂起/执行焦点回调

在父组件中维护isValidating状态标记当前是否有验证在进行,用pendingFocusCallback存储待执行的焦点回调:

import { useRef, useState } from "react";
import { AgGridReact } from "ag-grid-react";
import "ag-grid-community/styles/ag-grid.css";
import "ag-grid-community/styles/ag-theme-alpine.css";
import "ag-grid-enterprise";

import InputWrapper from "/src/components/InputWrapper";

const BaseGrid = () => {
  const gridRef = useRef(null);
  const [isValidating, setIsValidating] = useState(false);
  const [pendingFocusCallback, setPendingFocusCallback] = useState(null);

  const handleCellFocused = () => {
    console.log("CellFocused");
  };

  // 接收子组件的验证开始通知
  const handleValidationStart = () => {
    setIsValidating(true);
  };

  // 接收子组件的验证完成通知,执行挂起的回调
  const handleBlurComplete = () => {
    setIsValidating(false);
    if (pendingFocusCallback) {
      pendingFocusCallback();
      setPendingFocusCallback(null);
    }
  };

  // 自定义Grid焦点处理逻辑
  const handleGridCellFocused = () => {
    if (isValidating) {
      // 验证未完成,暂存回调
      setPendingFocusCallback(handleCellFocused);
    } else {
      // 验证已完成,直接执行
      handleCellFocused();
    }
  };

  return (
    <div
      className="ag-theme-alpine-dark"
      style={{
        width: "100%",
        height: "100%",
      }}
    >
      <AgGridReact
        ref={gridRef}
        columnDefs={[
          { headerName: "Make", field: "make" },
          {
            headerName: "Model",
            field: "model",
            cellRenderer: (params) => (
              <InputWrapper
                value={params.value}
                onValidationStart={handleValidationStart}
                onBlurComplete={handleBlurComplete}
              />
            ),
          },
        ]}
        rowData={[
          { make: "Toyota", model: "Celica" },
          { make: "Ford", model: "Mondeo" },
          { make: "Porsche", model: "Boxster" },
        ]}
        onCellFocused={handleGridCellFocused}
        style={{ width: "100%", height: "100%" }}
      />
    </div>
  );
};

export default BaseGrid;

原理说明

  1. 子组件Input失焦时,触发blurHandler启动异步验证,同时通过onValidationStart让父组件标记isValidating为true。
  2. AG Grid触发onCellFocused后,父组件检查到isValidating为true,将handleCellFocused存入pendingFocusCallback暂不执行。
  3. 子组件验证完成后,通过onBlurComplete让父组件标记isValidating为false,并执行暂存的回调,此时handleCellFocused才会触发。

最终日志顺序会符合预期:Start validating -> Recieved data -> End validating -> CellFocused。

内容的提问来源于stack exchange,提问作者Iman Rh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 03:15:05