如何在Reactjs中触发事件父子对子

时间:2017-04-26 19:08:13

标签: reactjs

我需要在父按钮的子组件中启动一个函数,但是我没有它,有人知道某种形式,我已经看过一些例子但我找不到可以帮助我的东西,因为他们只处理属性更改

这是我的代码 父母:

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'));

孩子

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>
    );
  }

3 个答案:

答案 0 :(得分:5)

不幸的是,这并不是React的功能。您正试图Menux.handleToggle作为onLeftIconButtonTouchTap道具的回调,对吧?因此,当有人点击左侧图标按钮时,您希望Menux组件执行handleToggle功能吗?

这不会有两个原因:

1)当你拨打Menux.handleToggle时,你没有在实例上调用它! Menux是对类本身的引用。它没有您期望的内部状态。而且,handleToggle是一种实例方法。这意味着它只能在Menux类的实例上执行。 2)您可能正在引用Menux类,但如上所述,这与React在呈现<Menux />元素时创建的实例不同。

很难充分阐明为什么这是错误的,只是在几个层面上根本就是错误的嘿嘿。简而言之:您无法调用类这样的类的功能,并期望它更改未指定的类的实例。

让我们走过那条路。现在,有一种令人费解的方式让你的代码以你编写的方式工作,但我认为最好帮助你理解一种更惯用的方式。也就是说,更多的“反应方式”可以完成您想要的任务。

我们希望“举起国家”。这个概念是这篇文章: https://facebook.github.io/react/docs/lifting-state-up.html

我强烈建议您阅读该文章。

为什么我们“举起状态?”在React中,子节点不会相互通信。只有孩子和父母互相沟通。事实上,父母通过提供数据和功能进行交流,孩子只通过调用父母给他们的功能进行交流。

想象一下,你是一个孩子,是5个兄弟姐妹中的一个。你们每个人都有一部手机,但你不知道兄弟姐妹的电话号码。您只有父母的电话号码。但是你需要向你的一些兄弟姐妹传达一些信息。你是做什么?你打电话给你父母的电话号码,转发他们的信息,父母会打电话给你的兄弟姐妹并将数据转发给他们。

这就是React的工作原理。

那么我们如何将这个应用到你的情况呢?当菜单打开时,让我们让菜单告诉菜单。这样,父母可以为Menux组件和AppBar组件提供一个功能,他们可以用它来说“嘿妈妈,你可以关闭菜单吗?”

我们将状态从Menux组件提升到App组件。

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>
        );
    }

}
啊哈哈!现在,我们的应用程序确定菜单何时关闭以及何时不关闭。这是真理的唯一来源!但是,如果他们想要更改父级中的状态,它会为AppBarMenux提供一些可以调用的函数。那么Menux将如何改变?

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>
    );
  }

它使用父传递它的函数来设置父级中的状态。一个漂亮,简单,可重复使用的组件!

这是React的做事方式。只有亲子的沟通,状态和功能传递给孩子,孩子们称这些功能在树中更高的状态。美丽!

“但是,但是......我真的不想做React方式!”

Fiiiiine 。值得庆幸的是,其他人以一种非常简单的方式回答(所以我没有:]),无需重新构建您的应用程序 ahem 更为惯用的方式。 / p>

答案 1 :(得分:2)

使用ref来保留对子组件的引用,以便您可以根据需要从父级调用handleToggle

<Menux ref={(menu)=>{this.menu = menu}}/>

然后:

<AppBar
  title="Aqui empezara todo"
  onLeftIconButtonTouchTap = {this.menu.handleToggle}
/>

答案 2 :(得分:0)

在这里找到: https://medium.com/@nugen/react-hooks-calling-child-component-function-from-parent-component-4ea249d00740

import React, { forwardRef, useRef, useImperativeHandle } from 'react';
export default function ParentFunction() {
    const childRef = useRef();
    return (
        <div className="container">
            <div>
                Parent Component
            </div>
            <button
                onClick={() => { childRef.current.showAlert() }}
            >
            Call Function
            </button>
            <Child ref={childRef}/>
        </div>
    )
}
const Child = forwardRef((props, ref) => {
    useImperativeHandle(
        ref,
        () => ({
            showAlert() {
                alert("Child Function Called")
            }
        }),
    )
    return (
       <div>Child Component</div>
    )
})