在子组件中调用父函数

时间:2018-07-24 15:31:45

标签: javascript reactjs

我试图将一个组件包装到另一个组件中,并从该“一个”组件中调用一个函数。

<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>

在父组件中,我有:

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

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

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

这里是游乐场:https://codesandbox.io/s/1ykllwnyq3

有解决方案吗?

3 个答案:

答案 0 :(得分:1)

承担这些组件的责任:

  • Parent:照顾国家。
  • Child1Child2:通用UI容器。
  • App:关注Parent的状态呈现方式。

这可以使用render props技术来完成。

在下面的示例中,没有将元素作为子元素传递给<Parent>a function is passed in instead

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>

答案 1 :(得分:0)

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>.

  

现在,可以根据以下方式呈现Child 2和Child1的内容   道具让我们明天说,您想要给Child 2视图其他的东西。   您可以像这样更改子组件。

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

这种方法怎么样?。

答案 2 :(得分:0)

您需要传递函数,并从道具中访问它。 克隆元素可让您将道具添加到所有子项。

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