简体   繁体   English

在子组件中调用父函数

[英]Call parent function in children component

I'm trying to wrap one component in another and call a function from that "one" component. 我试图将一个组件包装到另一个组件中,并从该“一个”组件中调用一个函数。

<Parent>
    <Child1>
    <button
        onClick={
        //toggleSomething
        console.log("Run function `toggleSomething` from parent")
        }
    >
        Change state 1
    </button>
    </Child1>

    <Child2>
    <button
        onClick={
        //toggleSomething
        console.log("Run function `toggleSomething` from parent")
        }
    >
        Change state 2
    </button>
    </Child2>
</Parent>

and in Parent component I have: 在父组件中,我有:

class Parent extends React.Component {
  state = {
    something: false
  };

  toggleSomething = () => {
    this.setState({
      something: true
    });
  };

  render() {
    return <div className="parentClasses">{this.props.children}</div>;
  }
}

Here is playground: https://codesandbox.io/s/1ykllwnyq3 这是游乐场: https : //codesandbox.io/s/1ykllwnyq3

There is a solution for that? 有解决方案吗?

Assuming these responsibilities for these components: 承担这些组件的这些责任:

  • Parent : Take care of the state. Parent :照顾国家。
  • Child1 and Child2 : Generic UI container. Child1Child2 :通用UI容器。
  • App : Takes care of how the state of Parent is rendered. App :照顾如何呈现Parent状态。

This can be done using the render props technique. 这可以使用渲染道具技术来完成。

In the example below, instead of passing an element as a children to <Parent> , a function is passed in instead . 在下面的示例中,不是将元素作为子元素传递给<Parent>而是传递了函数

 class App extends React.Component { render() { return ( <div> <Parent> {toggle => ( <React.Fragment> <Child1> <button onClick={toggle}>Change state 1</button> </Child1> <Child2> <button onClick={toggle}>Change state 2</button> </Child2> </React.Fragment> )} </Parent> </div> ); } } class Parent extends React.Component { state = { something: false }; toggleSomething = () => { this.setState({ something: true }); }; render() { return ( <div className="parentClasses"> {this.state.something.toString()} {this.props.children(this.toggleSomething)} </div> ); } } const Child1 = props => { return <div class="someClasses">{props.children}</div>; }; const Child2 = props => { return <div class="someOtherClasses">{props.children}</div>; }; const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement); 
 <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div id="root"></div> 

 class App extends React.Component { render() { return ( <div> <Parent> <Child1 /> <Child2 /> </Parent> </div> ); } } class Parent extends React.Component { state = { something: false }; toggleSomething = () => { console.log("now toggling !!"); this.setState({ something: true }); }; render() { const reactChildren = React.Children.toArray(this.props.children); const childrenWithProps = reactChildren.map(element => React.cloneElement(element, { toggleSomething: this.toggleSomething }) ); return <div className="parentClasses">{childrenWithProps}</div>; } } const Child1 = props => { return ( <div class="someClasses"> <button onClick={ //toggleSomething () => { props.toggleSomething(); console.log("Run function `toggleSomething` from parent"); } } > Change state 1 </button> </div> ); }; const Child2 = props => { return ( <div class="someOtherClasses"> <button onClick={() => { debugger; props.toggleSomething(); console.log("Run function `toggleSomething` from button 2"); }} > Change state 2 </button> </div> ); }; const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="root"></div>. 

Now the content of Child 2 and Child1 can be rendered according to props let say tomorrow, you want something else for Child 2 view. 现在,可以根据明天要说的道具来渲染Child 2和Child1的内容,您还需要有关Child 2视图的其他内容。 you can change your child Component like this. 您可以像这样更改子组件。

const Child2 = props => {
      const { RenderView, toggleSomething } = props
      //renderView is your view Component(stateless/statefull)
      return (
      <div class="someOtherClasses">
        {<RenderView toggleSomething={toggleSomething} />}
      </div>
      );
    };

How about this approach ?. 这种方法怎么样?

You need to pass the function, and access it from props. 您需要传递函数,然后从道具访问它。 Clone Element lets you add the prop to all children. 克隆元素可让您将道具添加到所有子项。

import React from "react";
import ReactDOM from "react-dom";

const Child1 = props => {
  return <button onClick={props.handler}>test</button>;
};

class Parent extends React.Component {
  state = {
    something: "nope"
  };

  toggleSomething = () => {
    this.setState({
      something: "yes"
    });
  };

  render() {


    const childrenWithProps = React.Children.map(
      this.props.children, child =>
          React.cloneElement(
          child, { handler: this.toggleSomething }
            )
      );

    return <div className="parentClasses">
    {this.state.something}
      {childrenWithProps}   
    </div>;
  }
}

const App = () => 
    <Parent>
        <Child1/> 
    </Parent>

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM