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;
原理说明
- 子组件Input失焦时,触发
blurHandler启动异步验证,同时通过onValidationStart让父组件标记isValidating为true。 - AG Grid触发
onCellFocused后,父组件检查到isValidating为true,将handleCellFocused存入pendingFocusCallback暂不执行。 - 子组件验证完成后,通过
onBlurComplete让父组件标记isValidating为false,并执行暂存的回调,此时handleCellFocused才会触发。
最终日志顺序会符合预期:Start validating -> Recieved data -> End validating -> CellFocused。
内容的提问来源于stack exchange,提问作者Iman Rh
相关产品推荐
相关产品推荐

