【问题标题】:Modifiying child state from parent component从父组件修改子状态
【发布时间】:2019-04-04 20:08:31
【问题描述】:

父组件在应用栏和绘图区域中包含一个按钮(我在其中拖放一些内容,这仅用于此处的上下文)。 我想保持子组​​件相对独立。

我想在单击此父组件中可用的按钮时更改子组件的状态。 当我使用不安全的“componentWillReceiveProps”时它可以工作(并且替换功能“很少使用”。 所以我从未成功地从父组件调用函数(在子组件中)。

什么是 React 的最佳实践?(我来自 PHP/GO/Python 背景)。

父类:

Class EditionView extends React.Component {

  constructor(props) {
    super(props)
    var drawingModel = this.emptyDrawingModel();
    this.state= {drawingModel:drawingModel};
  }

  emptyDrawingModel(){
    var drawingModel = []
    for (var i=0; i<3; i++) {
      drawingModel.push('')
    }
    return drawingModel;
  }

  resetDrawingArea() {
    console.log("tmp:", this);
    var drawingModel = this.emptyDrawingModel();
    this.setState({drawingModel: drawingModel});
  }

  render() {
    console.log(this.state);
    return (
      <div>
        <AppBar position="static" color="primary">
          <Typography variant="h6" color="inherit">
              Title
          </Typography>
          <Toolbar>
            <Button variant='contained' component='span' onClick={()=>{this.resetDrawingArea()}}>Reset</Button>
          </Toolbar>
        </AppBar>
        <Grid container>
          <Grid item sm={9}>
            <DrawingArea id='drawing' initialModel={this.state.drawingModel}/>
          </Grid>
        </Grid>
      </div>
    );
  }

}

export default EditionView;

儿童班

class DrawingArea extends React.Component {

  constructor(props) {
    super(props)
    this.state = {content:props.initialModel};
    //this.reset = this.reset.bind(this); 
    //this.reset = this.reset();
  }

  /*
  //WORKs but UNSAFE
  componentWillReceiveProps(){
    console.log("componentWillMount", this)
    this.setState({content: this.props.initialModel});
  }
  */

  reset(){
    console.log('in Drawing Area > reset')
    var model = this.props.initialModel;
    this.setState({content:model})
  }

  render() {
    console.log("render drawing area", this)
    var items = this.state.content.map((val, i) =>{
      var item;
      if (val === ''){
        // code for if 
      } else {
        // code for else
      }
      return item;
    });

    return(
      <div id="main-area">
        <Grid container>{items}</Grid>
      </div>
    )
  }
}

export default DrawingArea;

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    使用getDerivedStateFromProps:

    getDerivedStateFromProps 在调用 render 方法之前调用,无论是在初始挂载时还是在后续更新时。它应该返回一个对象来更新状态,或者返回 null 以不更新任何内容。

    class DrawingArea extends React.Component {
    
        static getDerivedStateFromProps(props) {
             return {
                content: props.initialModel
             }
        }
    
      ...
    }
    

    【讨论】:

      【解决方案2】:

      在您的子组件DrawingArea 中,由于您在render 函数中使用this.state,那么您可能需要实现生命周期事件getderivedstatefromprops

      另一种选择是在render 函数中使用this.props。这应该适用于您提供的简单示例。它将继续为您工作,直到您需要在DrawingArea 中存储状态的时间点(如果有)。

      【讨论】:

      • 谢谢,但我试图避免使用此功能。有没有办法从父级调用子级的函数。
      • 那么你将不得不使用来自 props 的值而不是组件的 state 对象。尝试将此添加到渲染函数,然后更新现有行。 const { initialModel: content } = this.props;var items = content.map((val, i) =&gt;{
      【解决方案3】:

      你不需要componentWillReceiveProps(),只要你在child的构造函数中就可以了

      constructor(props) {
        super(props)
          this.state = {
            content: this.props.initialModel
          }
      }
      

      只要你继续在你的子组件中使用 this.state.content

      当 this.state.drawingModel 发生变化时,父组件将重新渲染,使子组件接收它的新道具,只要它映射到子组件的状态,这个也会重新渲染

      【讨论】:

      • 子组件不是从父类继承的。
      • 我认为这不适用于提供的示例,因为在渲染函数中使用的是组件状态,随着道具的变化,当前不会在后续重新渲染时更新。
      猜你喜欢
      • 1970-01-01
      • 2015-04-15
      • 1970-01-01
      • 1970-01-01
      • 2014-10-09
      • 2017-07-10
      • 2016-12-21
      • 2016-12-26
      相关资源
      最近更新 更多