1

目前,我在运行我的 saga 时以 JSON 格式从 API 获取数据。当组件挂载时,获取过程开始。这意味着组件渲染两次。

现在,当数据作为道具可用时。我可以使用它来渲染它。

我的方法如下,我有一个:

  1. 具有初始状态的构造函数
  2. 我在“componentDidMount”中获取数据
  3. 我有一个函数,它从 props 中获取 JSON 属性并将其放入新变量中
  4. 当道具包含获取的数据时,我在我的 render() 函数中运行此函数

这种方法的问题:一旦组件运行数据变成“结构化”的函数,渲染函数就会循环,然后在一段时间后,属性的值会在控制台中显示警告消息。

我的问题

  1. render() 运行一次时如何防止循环?
  2. 我该如何设计这个,以便获取对象的特定属性合并到一个新对象中,以及如何

我希望我描述了关于我的问题的最重要的事情。这是代码:

class Dashboard extends React.Component {
constructor(props) {
    super(props);
    this.state = {
        deviceInfo: {
            name: "Initial Name",
            batLevel: "78%",
        }
    }
}

componentDidMount() {
    this.props.requestApiData();
}

updateDeviceInfoWithState (){
    const devices = (this.props.data.data);

    if(devices){
        const newDeviceInfo = this.state.deviceInfo;
        newDeviceInfo.name = devices[0].shadow.desired.payload.refAppData.name;
        newDeviceInfo.batLevel = devices[0].shadow.reported.payload.refAppData.batteryState.level;
        this.setState({
            deviceInfo: newDeviceInfo,
        });
    }
}

render() {
    this.updateDeviceInfoWithState()

    return (
        <div className='container'>
              <p> {this.state.deviceInfo.name} </p>
              <p> {this.state.deviceInfo.batLevel} </p>
        </div>
    )
}...
4

2 回答 2

1

在渲染方法中更新状态不是一个好习惯,因为它可能会导致无限循环。

在您的情况下,状态是多余的,因为您只从道具中获取数据,或者将其替换为默认值。而不是使用状态返回方法中的and,namebatLevelupdateDeviceInfoWithState方法中使用它render

示例(未测试):

class Dashboard extends React.Component {
  componentDidMount() {
      this.props.requestApiData();
  }

  updateDeviceInfoWithState (){
      const devices = this.props.data.data;

      if(devices){
        const device = devices[0].shadow;

        return {
          name: device.desired.payload.refAppData.name,
          batLevel: device.reported.payload.refAppData.batteryState.level
        };
      }

      return  {
        name: "Initial Name",
        batLevel: "78%",
      };
  }

  render() {
      const { name, batLevel } = this.updateDeviceInfoWithState();

      return (
          <div className='container'>
                <p> {name} </p>
                <p> {batLevel} </p>
          </div>
      );
}...

注意 1:如果您想将组件与状态解耦,最好强制执行简单的属性作为数据的输入。例如,此组件需要 和 作为name属性batLevel。它不需要知道设备数组、影子、有效负载等...您可以在 saga 中接收数据时准备数据,或者mapStateToProps.

注2:如果你真的需要你状态中的数据,你可以使用getDerivedStateFromProps生命周期方法(React 16.3),或者componentWillReceiveProps如果你使用旧版本更新状态。

于 2018-07-21T21:44:22.803 回答
0

对于这种情况,您可以像这样使用 ComponentWillRecieveProps 方法

componentWillRecieveProps(nextProps) {
// Condition as per ur requirement.
If(this.props.data != nextProps.data) {
    this.updateDeviceInfoWithState(nextProps)
}

}

此方法只会在您的组件道具更改时运行。

于 2018-07-21T21:51:03.623 回答