Search code examples
reactjsag-gridag-grid-react

My function does not wait for the child in the parent in reactjs


These are the samples of my components: Parent component:

import { useRef } 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 handleCellFocused = () => {
    console.log("CellFocused");
  };

  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) => {
              return <InputWrapper value={params.value} />;
            },
          },
        ]}
        rowData={[
          { make: "Toyota", model: "Celica" },
          { make: "Ford", model: "Mondeo" },
          { make: "Porsche", model: "Boxster" },
        ]}
        onCellFocused={handleCellFocused}
        style={{ width: "100%", height: "100%" }}
      />
    </div>
  );
};

export default BaseGrid;

Child component:

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

const InputWrapper = ({ value }) => {
  const handleValidation = async () => {
    console.log("Start validating");
    try {
      await axios.get("https://jsonplaceholder.typicode.com/todos/1");
      console.log("Recieved data");
    } catch (error) {
      console.log(error);
    } finally {
      console.log("End validating");
    }
  };

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

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

export default InputWrapper;

When the child component is blurred, a validation must happen and then the response sends to the parent. I put logs in my components to can be clear about what I want. The order that I want is : Start validating -> Recieved data -> End validating -> CellFocused The order that happens now: Start validating -> CellFocused -> Recieved data -> End validating

How do I stop the handleCellFocused function from executing until the child validation is complete?


Solution

  • The only way to achieve that is to put the validation on the parent component. You can't put the validation on the onBlur, you should put it on the onFocus.

    import "ag-grid-community/styles/ag-grid.css";
    import "ag-grid-community/styles/ag-theme-alpine.css";
    import "ag-grid-enterprise";
    import { AgGridReact } from "ag-grid-react";
    import { useRef } from "react";
    
    import InputWrapper from "/src/components/InputWrapper";
    
    // services/handleValidation.ts <- put the validation service on a separate file
    const handleValidation = async () => {
      console.log("Start validating");
      try {
        await axios.get("https://jsonplaceholder.typicode.com/todos/1");
        console.log("Recieved data");
      } catch (error) {
        console.log(error);
      } finally {
        console.log("End validating");
      }
    };
    
    const BaseGrid = () => {
      const gridRef = useRef(null);
    
    
      const handleCellFocused = async () => {
        await handleValidation();
        console.log("CellFocused");
      };
    
      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) => {
                  return <InputWrapper value={params.value} />;
                },
              },
            ]}
            rowData={[
              { make: "Toyota", model: "Celica" },
              { make: "Ford", model: "Mondeo" },
              { make: "Porsche", model: "Boxster" },
            ]}
            onCellFocused={handleCellFocused}
            style={{ width: "100%", height: "100%" }}
          />
        </div>
      );
    };
    
    export default BaseGrid;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js"></script>