最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Calling Child component function from Parent component in React.js - Stack Overflow

programmeradmin4浏览0评论

I am trying to call a function in my child ponent from a button click event in my parent ponent.

Parent Component:

class Parent extends Component{
    constructor(props){
        super(props);
        this.state = {
            //..
        }
    }

    handleSaveDialog = (handleSaveClick) => {
        this.handleSaveClick = handleSaveClick;
    }

    render(){
        return(
            <div>
                <Button onClick={this.openDialog}>Open Dialog</Button>
                <Dialog>
                    <DialogTitle id="form-dialog-title">Child Dialog</DialogTitle>
                    <DialogContent>
                        <Child handleSaveData={this.handleSaveDialog}/>
                    </DialogContent>
                    <DialogActions>
                        <Button onClick={this.handleSaveClick} color="primary">
                            Save
                        </Button>
                    </DialogActions>
                </Dialog>       
            </div>  
        );
    }
}

In the above code, the Parent ponent renders a Child ponent modal dialog (based on Material-UI) on click of a button. The Save button, part of the Dialog ponent in Parent, when clicked should call a save function in the Child ponent. As you can see, I have passed a callback function handleSaveDialog through the Childponent props named handleSaveData. The save button click will call handleSaveClick on the child, once the Child ponent mounts and passes the callback to the Parent ponent.

Child Component:

class Child extends Component{
    constructor(props){
        super(props);
        this.state = {
            //..
        }
    }

    ponentDidMount(){
        console.log('mount');
        this.props.handleSaveData( () => this.handleSaveClick());
    }

    handleSaveClick = () => {
        console.log('save clicked');
    }

    render(){
        return(
            <div>
                //..
            </div>      

        );
    }
}

In the above code, I am using the accessing the callback function passed by the Parent ponent props and binding it to the Child ponent's save fucntion handleSaveClick.

Problem:

When I click the Open Dialog button in Parent, for the first time, the Dialog mounts the Child ponent. However, the click on Save button does not work (no error). After, closing the dialog, when I reopen the Dialog and click on Save, the handleSaveClick in the Child dialog is triggered and a message is logged in the browser console. Any idea why this works on the second time and not the first time? Remember, the Child Component is mounted/loaded only when I click the Open Dialog on the Parent ponent.

References:

Call child method from parent

I am trying to call a function in my child ponent from a button click event in my parent ponent.

Parent Component:

class Parent extends Component{
    constructor(props){
        super(props);
        this.state = {
            //..
        }
    }

    handleSaveDialog = (handleSaveClick) => {
        this.handleSaveClick = handleSaveClick;
    }

    render(){
        return(
            <div>
                <Button onClick={this.openDialog}>Open Dialog</Button>
                <Dialog>
                    <DialogTitle id="form-dialog-title">Child Dialog</DialogTitle>
                    <DialogContent>
                        <Child handleSaveData={this.handleSaveDialog}/>
                    </DialogContent>
                    <DialogActions>
                        <Button onClick={this.handleSaveClick} color="primary">
                            Save
                        </Button>
                    </DialogActions>
                </Dialog>       
            </div>  
        );
    }
}

In the above code, the Parent ponent renders a Child ponent modal dialog (based on Material-UI) on click of a button. The Save button, part of the Dialog ponent in Parent, when clicked should call a save function in the Child ponent. As you can see, I have passed a callback function handleSaveDialog through the Childponent props named handleSaveData. The save button click will call handleSaveClick on the child, once the Child ponent mounts and passes the callback to the Parent ponent.

Child Component:

class Child extends Component{
    constructor(props){
        super(props);
        this.state = {
            //..
        }
    }

    ponentDidMount(){
        console.log('mount');
        this.props.handleSaveData( () => this.handleSaveClick());
    }

    handleSaveClick = () => {
        console.log('save clicked');
    }

    render(){
        return(
            <div>
                //..
            </div>      

        );
    }
}

In the above code, I am using the accessing the callback function passed by the Parent ponent props and binding it to the Child ponent's save fucntion handleSaveClick.

Problem:

When I click the Open Dialog button in Parent, for the first time, the Dialog mounts the Child ponent. However, the click on Save button does not work (no error). After, closing the dialog, when I reopen the Dialog and click on Save, the handleSaveClick in the Child dialog is triggered and a message is logged in the browser console. Any idea why this works on the second time and not the first time? Remember, the Child Component is mounted/loaded only when I click the Open Dialog on the Parent ponent.

References:

https://material-ui./ponents/dialogs/#form-dialogs

Call child method from parent

https://github./kriasoft/react-starter-kit/issues/909#issuement-390556015

Share Improve this question edited Jul 18, 2019 at 6:56 Souvik Ghosh asked Jul 18, 2019 at 6:49 Souvik GhoshSouvik Ghosh 4,61713 gold badges59 silver badges83 bronze badges 1
  • Can you put your code somewhere like codesandbox or in stackblitz. Its hard to tell from here. – Shubham Verma Commented Jul 18, 2019 at 6:59
Add a ment  | 

2 Answers 2

Reset to default 5

It will not work because if you console log this.handleSaveClick in render function it will be undefined as there is no re-render. So there are 2 ways to go for this:

  • Saving function in the state. Link: https://codesandbox.io/s/fervent-browser-gw75c
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      open: false
    };
  }

  openDialog = () => {
    this.setState(preState => ({
      open: !preState.open
    }));
  };

  handleSaveDialog = handleSaveRef => {
    this.setState({
      handleSaveClick: handleSaveRef
    });
  };

  render() {
    console.log("Render", this.handleSaveClick);
    return (
      <div>
        <Button onClick={this.openDialog}>Open Dialog</Button>
        <Dialog open={this.state.open}>
          <DialogTitle id="form-dialog-title">Child Dialog</DialogTitle>
          <DialogContent>
            <Child handleSaveData={this.handleSaveDialog} />
          </DialogContent>
          <DialogActions>
            <Button onClick={this.state.handleSaveClick} color="primary">
              Save
            </Button>
          </DialogActions>
        </Dialog>
      </div>
    );
  }
class Child extends Component {

  ponentDidMount() {
    console.log("mount");
    this.props.handleSaveData(this.handleSaveClick);
  }

  handleSaveClick = () => {
    console.log("save clicked");
  };

  render() {
    return <div>//..</div>;
  }
}

  • Using ref. Link: https://codesandbox.io/s/musing-kalam-nj29n
const childRef = React.createRef();
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      open: false
    };
  }

  openDialog = () => {
    this.setState(preState => ({
      open: !preState.open
    }));
  };

  handleSaveClick = () => {
    if (childRef.current) {
      childRef.current.handleSaveClick();
    }
  };

  render() {
    return (
      <div>
        <Button onClick={this.openDialog}>Open Dialog</Button>
        <Dialog open={this.state.open}>
          <DialogTitle id="form-dialog-title">Child Dialog</DialogTitle>
          <DialogContent>
            <Child ref={childRef} />
          </DialogContent>
          <DialogActions>
            <Button onClick={this.handleSaveClick} color="primary">
              Save
            </Button>
          </DialogActions>
        </Dialog>
      </div>
    );
  }
}
class Child extends Component {
  handleSaveClick = () => {
    console.log("save clicked");
  };

  render() {
    return <div>//..</div>;
  }
}

  • Using callback to save instance and than use arrow function:
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      open: false
    };
  }

  openDialog = () => {
    this.setState(preState => ({
      open: !preState.open
    }));
  };

  handleSaveDialog = handleSaveRef => {
    this.handleSaveClick = handleSaveRef;
  };

  render() {
    return (
      <div>
        <Button onClick={this.openDialog}>Open Dialog</Button>
        <Dialog open={this.state.open}>
          <DialogTitle id="form-dialog-title">Child Dialog</DialogTitle>
          <DialogContent>
            <Child handleSaveData={this.handleSaveDialog} />
          </DialogContent>
          <DialogActions>
            <Button onClick={() => this.handleSaveClick()} color="primary">
              Save
            </Button>
          </DialogActions>
        </Dialog>
      </div>
    );
  }
}
class Child extends Component {
  ponentDidMount() {
    console.log("mount");
    this.props.handleSaveData(this.handleSaveClick);
  }

  handleSaveClick = () => {
    console.log("save clicked");
  };

  render() {
    return <div>//..</div>;
  }
}

You will need to use arrow function in onClick as it will create a new function every time we click and thus getting a new instance of handleClick. And if you pass this.handleClick it won't work because it is undefined. You can check this by logging the value of this.handleClick in render function.


Note: Use the 2 option its more reliable.

Hope this helps!

Well, I don't know why you have this sort of scenario but the first things that es in my mind is that you can write handleSaveClick method in your Parent ponent. And in case you need to use that function on any action that might be happening in your child ponent, you can pass this function as a prop from parent ponent. So your both cases can be handled

  • You can call this method on something happening in parent ponent
  • You can use the same method on any action that is happening in your child ponent.

If still you think that you have to define the method in your child ponent, you can use the refs

发布评论

评论列表(0)

  1. 暂无评论