Home > Software engineering >  How to call a function in a parent component from a child component when there is a successful updat
How to call a function in a parent component from a child component when there is a successful updat

Time:08-15

I have two components. My parent component, IntakeDetails, calls the child component, ActionsTab, within a TabPanel. The Actions component contains a table and Dialogs. When I close any Dialog in Actions, I want to call a function in IntakeDetails called fetchDetails. How would I go about doing this?

fetchDetails pulls some crucial data that is changed in backend api's when certain criteria in ActionsTab are met. I want to call fetchDetails every time there is a successful update in ActionsTab.

This is a basic overview of my code.

IntakeDetails

export default function IntakeDetails2() {
    const [details, setDetails] = useState("");
    const [busy, setBusy] = useState(false);
    const [value, setValue] = useState(1);  // Tab panel index

    const fetchDetails = async () => {
        setBusy(true);
        if (value === 1) {
            const response = await fetch(`/api/fiscalyears/${fy}/intakes/${params.id}/details2`);
            const detailsResp = await response.json();
            setDetails(detailsResp);
        }
        setBusy(false);
    };

....
    return (
            <Tabs value={value} onChange={handleChange} aria-label="basic tabs example">
                <Tab label="Solutioning" className={classes.tabs} />
                <Tab label="Actions" className={classes.tabs} disabled={details?.IntakeID === 0} />
            </Tabs>
            <TabPanel value={value} index={1}>
                ....
            </TabPanel>
            <TabPanel value={value} index={4}>
                <ActionsTab />
            </TabPanel>
    );
}

ActionsTab

function ActionsTab() {
...
    const updateAction = async (e) => {
        e.preventDefault();
        const updateResponse = await fetch(`/api/actions/${action.Id}`, {
            method: "PATCH",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(action),
        });
        const updateActionResp = await updateResponse.json();
        if (updateResponse.ok) {
            setSuccessOpen(true);
            // I would like to call the fetchDetails() function here 
        } else {
            setErrorMessage(updateActionResp?.error);
            setErrorOpen(true);
        }
    };

    const onMessageClose = () => {
        setSuccessOpen(false);
        fetchActions();
    };
}

CodePudding user response:

Add your callback as a prop in ActionsTab, and pass it from IntakeDetails.

Example:

function ActionsTab(props) {  // props get passed as the 1st argument from parent
  // ...

  const updateAction = async (e) => {
        e.preventDefault();
        const updateResponse = await fetch(`/api/actions/${action.Id}`, {
            method: "PATCH",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(action),
        });
        const updateActionResp = await updateResponse.json();
        if (updateResponse.ok) {
            setSuccessOpen(true); 
            // add your function call here - this will call the func
            // that was passed from the parent
            props.onUpdate() // you can pass arguments here if you want
        } else {
            setErrorMessage(updateActionResp?.error);
            setErrorOpen(true);
        }
    };

  // ...
}

And then:

export default function IntakeDetails2() {

  // ...

  return (
    // ...
    <TabPanel value={value} index={4}>
      {/* pass the function you want to call when ActionsTab triggers update */}
      <ActionsTab onUpdate={() => fetchDetails()} />
    </TabPanel>
  )
}

CodePudding user response:

The simplest thing you can do is to pass the fetchDetails function as property to your ActionsTab ->

<TabPanel value={value} index={4}>
    <ActionsTab fetchDetails={fetchDetails} />
</TabPanel>

After you used destructure it from your props ->

function ActionsTab({ fetchDetails }) {

you can use it within updateAction ->

if (updateResponse.ok) {
    setSuccessOpen(true);
    // I would like to call the fetchDetails() function here 
    await fetchDetails()
}

FYI: I see that you want Error handling. I suggest you wrap your axios call in try and catch to handle any error while fetching.

  • Related