Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how trigger event parent to child in Reactjs

Tags:

reactjs

I need to launch a function that I have in the child component of a parent button but I have not got it, someone knows some form, I have already seen some examples but I can not find something that can help me since they only handle property changes

this is my code parent:

import React from 'react';
import ReactDom from 'react-dom';
import AppBar from 'material-ui/AppBar';
import injectTapEventPlugin from 'react-tap-event-plugin';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import Menux from '../componentes/menux';

class App extends React.Component {
     constructor(props) {
    super(props);
  }
  render() {
    return (
<div>
         <AppBar
    title="Aqui empezara todo"
    onLeftIconButtonTouchTap = {Menuxr.handleToggle}
  />
     <Menux />
</div>
        );
    }

}

injectTapEventPlugin();
ReactDom.render( <MuiThemeProvider><App/></MuiThemeProvider>,document.getElementById('workspace'));

child

import React from 'react';
import Drawer from 'material-ui/Drawer';
import AppBar from 'material-ui/AppBar';
import MenuItem from 'material-ui/MenuItem';
import RaisedButton from 'material-ui/RaisedButton';

export default class Menux extends React.Component {

  constructor(props) {
    super(props);
    this.state = {openmenu: false};
  }

  handleClose = () => this.setState({openmenu: false});
  handleToggle = () => this.setState({openmenu: !this.state.openmenu});
  render() {
    return (
      <div>
        <RaisedButton
          label="Toggle Drawer"
          ref="menu"
          onTouchTap={this.handleToggle}/>
        <Drawer width={200} openSecondary={false} open={this.state.openmenu} >
          <AppBar title="menu"
                   onLeftIconButtonTouchTap = {this.handleClose}
          />
            <MenuItem onTouchTap={this.handleClose}>Mi perfil</MenuItem>
            <MenuItem onTouchTap={this.handleClose}>Mis usuarios</MenuItem>
            <MenuItem onTouchTap={this.handleClose}>Mis unidades</MenuItem>
        </Drawer>
      </div>
    );
  }
like image 519
Jesus Juarez Avatar asked Apr 26 '17 19:04

Jesus Juarez


People also ask

How do you trigger an event from parent to child in React?

To pass an onChange event handler to a child component in React: Define the event handler function in the parent component. Pass it as a prop to the child component, e.g. <Child handleChange={handleChange} /> . Set it to the onChange prop on the input field in the child.

How do you pass event from parent component to child component?

In a parent component you can use @ViewChild() to access child component's method/variable. Use the @Input() decorator in your child component to allow the parent to bind to this input. To bind a property from parent to a child you must add in you template the binding brackets and the name of your input between them.

How do you trigger events in React?

To add the click event in React using plain JavaScript, you need to use addEventListener() to assign the click event to an element. Create one <button> element as ref props so that it can be accessed to trigger the click event.


1 Answers

That's not how React functions, unfortunately. You are trying to use Menux.handleToggle as the callback of the onLeftIconButtonTouchTap prop, right? So when someone clicks the left icon button, you want the Menux component to execute the handleToggle function?

That won't work for two reasons:

  1. When you call Menux.handleToggle, you are not calling it on an instance! Menux is a reference to the class itself. It doesn't have the internal state that you are expecting. Moreover, handleToggle is an instance method. This means it can only be executed on instances of the Menux class.
  2. You may be referencing the Menux class, but as discussed above, that is not the same instance that React creates when you render the <Menux /> element.

It's really hard to adequately articulate why it's wrong, it's just fundamentally wrong on a few levels hehe. Long story short: you just cannot call the function of a class like that and expect it to change an instance of that class that is not being specified.


Let's move past that. Now, there's a convoluted way of getting your code to work in the way you've written it, but I think it's better to help you understand a more idiomatic way of doing it. That is to say, a more "React way" of getting done what you want.

We want to "Lift the State Up". This concept is this article: https://facebook.github.io/react/docs/lifting-state-up.html

I highly recommend reading that article.

Why do we "lift state up?" Well in React, child nodes don't communicate with each other. Only children and parents communicate with each other. In fact, parents communicate by providing data and functions, children communicate only by calling the functions parents give them.

Imagine you're a kid, one of 5 siblings. You each have a cell phone, but you don't know the phone numbers of your siblings. You only have your parents phone number. But you need to convey some information to some of your siblings. What do you do? You call your parents phone number, relay them the information, and the parents will call your siblings and relay the data to them.

That's how React works.

So how do we apply this to your situation? Instead of the Menu determining itself when it's open, let's have the parent tell the Menu when it's open. This way, the parent can give both the Menux component and the AppBar component a function that they can use to say "Hey mom, can you close the menu?"

We will lift the state from the Menux component to the App component.

class App extends React.Component {
     constructor(props) {
    super(props);
    this.state = {
       openmenu: false
    }
  }
  handleClose = () => this.setState({openmenu: false});
  handleToggle = () => this.setState({openmenu: !this.state.openmenu});
  render() {
    return (
<div>
         <AppBar
    title="Aqui empezara todo"
    onLeftIconButtonTouchTap = {this.handleToggle}
  />
     <Menux openmenu={this.state.openmenu} handleToggle={this.handleToggle} handleClose={this.handleClose} />
</div>
        );
    }

}

Ah ha! Now our App determines when the menu is closed and when it's not. It is the single source of truth! But, it provides AppBar and Menux with some functions that they can call if they want to change the state in the parent. So how will Menux change?

export default class Menux extends React.Component {

  render() {
    return (
      <div>
        <RaisedButton
          label="Toggle Drawer"
          ref="menu"
          onTouchTap={this.props.handleToggle}/>
        <Drawer width={200} openSecondary={false} open={this.props.openmenu} >
          <AppBar title="menu"
                   onLeftIconButtonTouchTap = {this.props.handleClose}
          />
            <MenuItem onTouchTap={this.props.handleClose}>Mi perfil</MenuItem>
            <MenuItem onTouchTap={this.props.handleClose}>Mis usuarios</MenuItem>
            <MenuItem onTouchTap={this.props.handleClose}>Mis unidades</MenuItem>
        </Drawer>
      </div>
    );
  }

It uses the functions that the parent passed it in order to set the state in the parent. A nice, easy, reusable component!

This is the React way of doing things. Parent-child only communication, state and functions passed down to children, children call those functions to change state higher up in the tree. Beautiful!


"But, but, but...I really don't want to do things the React way!"

Fiiiiine. Thankfully, someone else answered (so I don't have to :]) with a very simple way to accomplish what you want to do, without having to restructure your application to ahem a more idiomatic way.

like image 66
aaronofleonard Avatar answered Oct 11 '22 18:10

aaronofleonard