开发者问题收集

在父组件中设置状态,以便子组件可以访问状态

2018-07-09
373

我正在尝试为我的网络游戏的一部分设置状态,以允许玩家上传他们的怪物的照片。

我有一个名为 <MonsterContainer> 的父组件。它包含两个子组件: <MonsterPortraitUpload><MonsterViewer>

我正在 <MonsterContainer>

<MonsterPortraitUpload> 中设置状态,将允许用户上传照片,它将添加到状态中的 MonsterPortraits 数组中。

<MonsterViewer> 将显示数组中怪物的所有照片。

我如何确保我的两个子组件可以访问此状态?

这是我现在所拥有的:

class MonsterContainer extends Component {

constructor() {
    super();
    this.state = {
        MonsterPortraits: []
    };
}

render() {
    const { monsterId } = this.props;
    return (
        <div>
            <div>
                <MonsterPortraitUpload monsterId={monsterId}/>
            </div>
            <div>
                <MonsterViewer monsterId={monsterId}/>
            </div>
        </div>
    );
}
}

现在,我正尝试在 <MonsterViewer> 中将状态写入控制台,但我得到了这个错误:

Uncaught TypeError: Cannot read property 'MonsterPortraits' of null

2个回答

子组件 无法 访问父组件的状态;数据流单向流动:向下。

如果子组件需要访问父组件的状态,则应将该状态作为属性传递。

如果这不能满足您的需求(例如,深层嵌套的层次结构,子组件需要在更高级别更新状态),那么您可能需要不同的状态管理系统,例如 Redux/etc。

就您而言,如所示,将肖像数组向下传递给 <MonsterView /> 似乎就足够了,而 <MonsterPortraitUpload /> 将采用添加到容器状态的函数 prop(例如,添加肖像)。

这是 React 和类似组件中的一个基本概念:哑组件,智能容器。转储组件获取数据和函数,容器管理状态。这会在深层层次结构中崩溃,因为您最终必须将属性向下传递多个级别。

可能 通过 React Contexts 解决,或者将属性注入克隆的子项等,但这些是否是好的解决方案取决于您的架构。通常,不同形式的状态管理可以通过引入一层薄薄的复杂性来解决此类问题。

要修改容器的状态,您需要传递一个处理程序;非常即兴:

class MonsterContainer extends Component {
  // Etc.

  addPortrait(someData) {
    this.setState([ ...this.state.MonsterPortraits, someData ]);
  }

  render() {
    // Etc.
    <MonsterPortraitUpload addHandler={this.addPortrait} /> 

<MonsterPortraitUpload /> 中,您需要创建数据(例如,表单),然后在用户操作(例如,按下按钮)时,您调用容器的处理程序函数传递任何数据:

class MonsterPortraitUpload extends Component {
  addPortait() {
    // Marshall the data however, then
    this.props.addPortrait(newData);
  }
  // Etc.
}
Dave Newton
2018-07-09

您显示的错误绝对不是来自附加代码。 如果您需要向下传递状态,请使用此

class MonsterContainer extends Component {
  constructor() {
      super();
      this.state = {
          MonsterPortraits: []
      };
  }

  render() {
    return (
        <div>
            <div>
                <MonsterPortraitUpload monsterPortraits={this.state.MonsterPortraits}/>
            </div>
            <div>
                <MonsterViewer monsterPortraits={this.state.MonsterPortraits}/>
            </div>
        </div>
    );
  }
}

因此,在 MonsterPortraitUpload 组件中,您可以使用 this.props.monsterPortraits

Sasha Kos
2018-07-09