1

我正在将来自 Parent 组件的 props 传递到 Child 的状态,但它们不同步。

我尝试了什么:

  1. 状态更新可能是异步的,我已经使用回调而不是返回对象来处理这一点。
  2. 对象是通过引用传递的,但我使用的道具是一个字符串。

我正在使用 React 16 和 es6 语法

class Parent extends React.Component {
  state = {
   isHidden: false
  }
  render() {
   console.log('PROPS from PARENT', this.state.isHidden)
   return <div>
     <Child isOpen={this.state.isHidden} />
     <button onClick={this.toggleModal}>Toggle Modal</button>
    </div>
   }
  toggleModal = () => this.setState(state => ({isHidden: !state.isHidden}))
 }

class Child extends React.Component {
  state = {
   isHidden: this.props.isOpen
  }
  render() {
    console.log('STATE of CHILD:',this.state.isHidden)
    return <p hidden={this.state.isHidden}>Hidden:{this.state.isHidden}</p>
  }
}
ReactDOM.render(<Parent/>, document.getElementById('app'));

这里是一个codepen PEN - 注意redered元素应该根据状态隐藏(状态取决于父级的道具)

控制台显示我的道具和状态不相等

4

4 回答 4

2

如果您从孩子中删除不需要的状态定义,并仅使用从父母传递的道具,我相信孩子的行为会有意义。

如果要在child中使用state,构造函数设置是不够的,需要在props变化时设置child state。

Console.log 是异步的,所以你不能在这里依赖它。

于 2018-05-30T05:11:13.177 回答
2

componentWillReceiveProps发生变化时使用which call props

class Child extends React.Component {
    state = {
        isHidden: this.props.isOpen
    }
    componentWillReceiveProps(props) {

        if (props.isOpen != this.state.isHidden)
            this.setState({
                isHidden: props.isOpen
            })

    }
    render() {
        console.log('STATE of CHILD:', this.state.isHidden)
        return <p hidden = {
            this.state.isHidden
        } > Hidden: {
            this.state.isHidden
        } < /p>
    }
}
于 2018-05-30T05:11:34.707 回答
1

您的孩子的状态不会随着道具的变化而改变,因为组件对构造函数中的状态变化一无所知。当您依赖道具来构建本地状态时,这是一个常见的陷阱。您可以使用 @Nishant Dixit 的答案中所示的 componentWillReceiveProps 。但是,从 React 16.3 开始,我们为此提供了 getDerivedStateFromProps 函数(lifecylce 方法)。

static getDerivedStateFromProps( props, state) {
    if( props.isOpen === state.isHidden) {
      return null;
    }
    return {
      isHidden: props.isOpen,
    }
  }

在这里,我们正在比较我们的 prop 和 state,如果有变化,我们将返回所需的 state。无需使用 this.setState。

包括异步渲染的相关 API 更改博客文章: https ://reactjs.org/blog/2018/03/27/update-on-async-rendering.html

于 2018-05-30T05:31:33.527 回答
1

尽管其他答案将使代码正常工作,但实际上有一个更优雅的解决方案:)

您的子组件不需要任何状态,因为状态由 Parent 管理(它管理isHidden属性并将其传递给子组件)。所以子组件应该只关心道具。

尝试像这样编写组件,我相信它应该可以工作:

class Child extends React.Component {
  render() {
    return <p hidden={this.props.isHidden}>Hidden:{this.props.isHidden}</p>
  }
}

在 React 团队工作的 Dan Abramov 发布了关于这个问题的推文 - 本质上是说你应该认真考虑在组件中使用状态之前是否可以只使用 props https://twitter.com/dan_abramov/status/979520339968516097?lang=en

于 2018-05-30T11:00:14.443 回答