0

I am trying to reducing my code complexity to express by defining just skeleton code bellow. have to trigger the toggleModel of the child component

import React, { useState } from "react";
import "./styles.css";

const ChildComponent = (props) => {
  // .... some useStates 
  const toggleModel = () => {
    // have to trigger this methoud once user clicks on button
    // have to change some states here 
  };
  return (
     <div>
       {props.children}
        ...... other things .......
     </div>
  );
};

export default function ParentComponet() {
  return (
    <div className="App">
      Hello
      <ChildComponent>
        <button
          type="button"
          onClick={() => {
            // here i have to trigger the toggleModel function of ChildComponent
          }}
        >
          Toggle Model
        </button>
      </ChildComponent>
    </div>
  );
}

i am rendering child component by sending children elements, have to trigger the toggleModel of the child component it will reduce my 70 % redundant code at our application. is there any way to achieve the same codesandbox. Thank you in advance

Sunil Kumar
  • 420
  • 4
  • 13
  • Does this answer your question? [How to call child component function from Parent in react](https://stackoverflow.com/questions/61734117/how-to-call-child-component-function-from-parent-in-react) – Vandesh Jan 05 '21 at 15:38
  • sorry, it's looks quite different – Sunil Kumar Jan 05 '21 at 15:41

3 Answers3

3

You can use useState and useEffect to pass state down and react to it.

import React, { useState } from "react";
import "./styles.css";

const ChildComponent = ({visible, children, setVisible}) => {
  React.useEffect(() => {
    const toggleModel = () => {
      alert('Visible changes to ' + visible )
    };
      toggleModel()
  }, [visible])
  return <div>{children}</div>;
};

export default function ParentComponet() {
  const [visible, setVisible] = React.useState(false)
  return (
    <div className="App">
      Hello
      <ChildComponent visible={visible} setVisible={setVisible}>
        <button
          type="button"
          onClick={()=> setVisible(!visible)}
        >
          Toggle Model
        </button>
      </ChildComponent>
    </div>
  );
}

https://codesandbox.io/s/objective-ramanujan-j3eqg

The alternative is use @yaiks answer.

Njuguna Mureithi
  • 3,506
  • 1
  • 21
  • 41
0

You can take a look at this question here, it can help you.

But I would say it's not a good practice to call a child function from the parent. Usually what I would do is to "lift up" the method to the parent, and pass down to the child if possible.

yaiks
  • 576
  • 3
  • 13
0

Here is another way to call your ChilComponent's function - using forwardRef:

import React, { useState, useImperativeHandle, forwardRef } from "react";
import "./styles.css";

const ChildComponent = forwardRef((props, ref) => {
  useImperativeHandle(ref, () => ({
    toggleModel() {
      alert("alert from ChildComponent");
    }
  }));

  return <div>{props.children}</div>;
});

export default function ParentComponet() {
  return (
    <div className="App">
      Hello
      <ChildComponent ref={ChildComponent}>
        <button
          type="button"
          onClick={() => ChildComponent.current.toggleModel()}
        >
          Toggle Model
        </button>
      </ChildComponent>
    </div>
  );
}

Sandbox: https://codesandbox.io/s/pensive-jones-lw0pf?file=/src/App.js

My answer is courtesy of @rossipedia: https://stackoverflow.com/a/37950970/1927991

codemonkey
  • 7,325
  • 5
  • 22
  • 36