【问题标题】:React: how to propagate state to enclosing parentReact:如何将状态传播到封闭的父级
【发布时间】:2020-11-07 05:31:04
【问题描述】:

我有 2 个类来提供模式对话框功能:

import React from 'react'
import Modal from 'react-modal'

export default class ModalBase extends React.Component {

  state = { show:false }

  handleOpen = opts => {
    this.setState( { ...opts, show:true } )
    console.info( 'ModalBase handleOpen', this.constructor.name, 'show', this.state.show )
  }

  handleClose = () => this.setState( { show:false } )

  render() {
    console.info( 'ModalBase render show', this.state.show )

    return <Modal isOpen={this.state.show} onRequestClose={this.handleClose} className="Modal" overlayClassName="Overlay">
      {this.props.children}
    </Modal>
  }
}

export default class InfoPopup extends ModalBase {
  
  state = { ...this.state, tech:{} }

  render() {
    console.info('InfoPopup render show', this.state.show)

    return ( 
      <ModalBase>
       <div/><div/>
      </ModalBase>
    )
  }
}

当我调用InfoPopup.handleOpen({a:42}) 时,控制台中会显示以下内容:

ModalBase handleOpen InfoPopup show true
InfoPopup render show true 
ModalBase render show false

所以,ModalBase 的 state.show 没有改变,因此弹出窗口没有显示。

我应该如何正确地将状态传播到封闭的父对象?

TIA

【问题讨论】:

    标签: reactjs modal-dialog state


    【解决方案1】:

    使用组合而不是继承

    来自 React 文档:

    React 具有强大的组合模型,我们建议使用组合而不是继承来重用组件之间的代码。

    见:https://reactjs.org/docs/composition-vs-inheritance.html

    所以不建议export default class InfoPopup extends ModalBase

    1。让InfoPopup 渲染ModalBase 但跟踪打开/关闭状态

    你可以把它转过来,有一个通用的BaseModal 组件用于模态样式,你可以传递诸如titlecontent 之类的道具。 InfoPopup 跟踪打开/关闭状态。从同一个 React 文档页面:

    function Dialog(props) {
      return (
        <FancyBorder color="blue">
          <h1 className="Dialog-title">
            {props.title}
          </h1>
          <p className="Dialog-message">
            {props.message}
          </p>
          {props.children}
        </FancyBorder>
      );
    }
    
    class SignUpDialog extends React.Component {
      constructor(props) {
        super(props);
        this.handleChange = this.handleChange.bind(this);
        this.handleSignUp = this.handleSignUp.bind(this);
        this.state = {login: ''};
      }
    
      render() {
        return (
          <Dialog title="Mars Exploration Program"
                  message="How should we refer to you?">
            <input value={this.state.login}
                   onChange={this.handleChange} />
            <button onClick={this.handleSignUp}>
              Sign Me Up!
            </button>
          </Dialog>
        );
      }
    
      handleChange(e) {
        this.setState({login: e.target.value});
      }
    
      handleSignUp() {
        alert(`Welcome aboard, ${this.state.login}!`);
      }
    }
    

    2。渲染 ModalBase 并将模态的类型作为 prop 传递

    您也可以始终呈现ModalBase 以获取信息、警告、错误模式等。然后将模式的类型作为道具传递给ModalBaseModalBase 根据该类型属性确定一些细节。

    3。使用渲染道具

    此处描述:https://reactjs.org/docs/render-props.html

    ModalBase 接受一个函数作为子属性。

    所以在InfoPopup:

    <ModalBase>
      {({ toggle }) => (
        <button onClick={toggle} />
      )}
    </ModalBase>
    

    ModalBase:

    render() {
      return <Modal ...>{this.props.children({ toggle: this.openOrClose })}</Modal>
    }
    

    4。将组件传递给ModalBase 以在打开时呈现

    2 的一些变体。您还可以将组件作为道具传递给ModalBase,它应该在打开时显示。

    <ModalBase
      modalContent={<InfoPopup />}
    />
    

    【讨论】:

    • 1.是我的出发点,这正是我想要避免的。我想将show 状态保留在父/封闭组件中
    • 是的 :) 所以我认为 2、3 和 4 使这成为可能?
    • 不,与第一个天真的实现相比,它只会使代码更加复杂
    猜你喜欢
    • 2017-04-04
    • 2020-09-09
    • 2015-03-19
    • 1970-01-01
    • 1970-01-01
    • 2016-09-26
    • 2021-04-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多