如何在Reactjs中触发父组件到子组件的事件

15

我需要启动一个在子组件中的函数,但我没有它,有人知道什么方法吗?我已经看了一些例子,但我找不到能帮助我的东西,因为它们只处理属性更改。

这是我的代码 父组件:

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>
    );
  }
4个回答

18
很遗憾,React并不是这样工作的。你试图将Menux.handleToggle作为onLeftIconButtonTouchTap属性的回调函数使用,对吧?所以当有人点击左侧图标按钮时,你希望Menux组件执行handleToggle函数?但这有两个问题:
  1. 当你调用Menux.handleToggle时,你并没有在实例上调用它!Menux是类本身的引用。它没有你期望的内部状态。此外,handleToggle是实例方法。这意味着它只能在Menux类的实例上执行。
  2. 你可能正在引用Menux类,但正如上面讨论的那样,这不是React在渲染<Menux />元素时创建的同一实例。
很难充分表达为什么它是错误的,因为它在几个层面上都是根本性的错误。长话短说:你不能这样调用一个类的函数,并期望它改变未指定的该类实例。
让我们超越这个。现在,有一种复杂的方法可以使您编写的代码按照您的意愿工作,但我认为帮助您理解更符合惯用方式的方法更好。也就是说,以更“React的方式”完成您想要的操作。
我们想要“提升状态”。该概念在此文章中: 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>
        );
    }

}

啊哈!现在我们的应用程序确定菜单何时关闭以及何时不关闭。它是唯一的真相来源!但是,它为AppBar和Menux提供了一些函数,如果它们想要改变父级中的状态,它们可以调用这些函数。那么,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 的做事方式。只有父子之间的通信,状态和函数向下传递给子组件,子组件调用这些函数来改变树中更高层次的状态。非常美妙!
"But, but, but...我真的不想按照React的方式做事!"
"好吧。幸运的是,有人回答了(所以我不必:]),提供了一种非常简单的方法来实现你想要做的事情,而不必重构你的应用程序以更符合惯用方式。"

6

使用ref来保留对子组件的引用,这样您就可以在父组件中随意调用handleToggle

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

然后:

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

2

在这里找到:

https://medium.com/@nugen/react-hooks-calling-child-component-function-from-parent-component-4ea249d00740 该文涉及到IT技术,讲解了如何使用React Hooks来实现从父组件调用子组件函数的方法。如果您需要更好地理解React Hooks的使用,请查看该文章。
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>
    )
})

那是一个非常好的解决方案。 - Alauddin Ahmed

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接