将函数传递给this.props.children

时间:2019-09-05 20:22:40

标签: javascript reactjs

最近看来,React不会像过去那样将this.props.children视为函数。

我刚刚编写了一个Modal组件,并将其closeModal函数传递给子组件,

render() {
  return (
    <Modal>
      {
        (closeModal) => {
          return (<span onClick={closeModal}>Click to close modal</span>)
        }
      }
    </Modal>
  )
}

模态看起来像这样

class Modal extends React.Component {
  constructor(props) {
    this.state = { show: true }

    this.close = this.closeModal.bind(this)
  }

  closeModal() {
    this.setState({ show: false })
  }

  render() {
    if (!this.state.show)
      return null

    return (
      <div>
        { this.props.children }
      </div>
    )
  }
}

我试图通过this.props.children({ closeModal: this.closeModal })传递函数作为prop,根据最新的React 16.9,猜猜this.props.children不是函数。

作为使用GraphQL的人们的参考,我看到Apollo客户的<Mutation><Query>的工作方式大致相同。

如何实现?

编辑:为什么不重复? 因为其他答案依赖this.props.children作为函数,而最近React现在却呈现错误,要求针对此问题采取新的方法: TypeError:this.props.children不是函数

2 个答案:

答案 0 :(得分:2)

我已经回答了必要的更新,以显示问题所在以及如何在下面的行内进行更改。

class Modal extends React.Component {
  constructor(props) {
    // 1️⃣ Make sure to make `props` available in this component.
    // This call is what makes `this.props` call to be available within `Modal`.
    super(props);

    this.state = { show: true };

    // 2️⃣ Assign a newly bound method to the matching class method
    // this.close = this.closeModal.bind(this);
    this.closeModal = this.closeModal.bind(this);
  }

  closeModal() {
    this.setState({ show: false });
  }

  render() {
    if (!this.state.show) return null;

    // 3️⃣ Pass the modal handler to children
    // If you had kept `this.close`, then when you pass the handler
    // "{ closeModal: this.close }" instead of "{ closeModal: this.closeModal }"
    return <div>{this.props.children({ closeModal: this.closeModal })}</div>;
  }
}

function App() {
  return (
    <div className="App">
      <Modal>
        {/* 4️⃣ destructure `closeModal` */}
        {({ closeModal }) => {
          return <button onClick={closeModal}>Click to close modal</button>;
        }}
      </Modal>
    </div>
  );
}

由于Emile Bergeron具有kindly pointed out,您可以传递this.props.children(this.close)而不是对象,但是我发现它更易于阅读/使用。

您可以分叉并尝试或运行下面的代码片段〜
感谢Emile Bergeronthe comment的建议〜
Edit so.answer.57812519

class Modal extends React.Component {
  constructor(props) {
    super(props);

    this.state = { show: true };

    // this.close = this.closeModal.bind(this);
    this.closeModal = this.closeModal.bind(this);
  }

  closeModal() {
    this.setState({ show: false }, () => {
      console.log(`Modal closed`);
    });
  }

  render() {
    if (!this.state.show) return null;

    return <div>{this.props.children({ closeModal: this.closeModal })}</div>;
  }
}

function App() {
  return (
    <div className="App">
      <Modal>
        {({ closeModal }) => {
          return (
            <button type="button" onClick={closeModal}>
              Click to close modal
            </button>
          );
        }}
      </Modal>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>

<div id="root"></div>

答案 1 :(得分:0)

尝试这个

class Modal extends React.Component {

  constructor(props) {
    this.state = { show: true }

    this.close = this.closeModal.bind(this)
  }

  closeModal() {
    this.setState({ show: false })
  }

  render() {
    if (!this.state.show)
      return null

    return (
      <div>
        { this.props.children(this.close) }
      </div>
    )
  }
}