【问题标题】:Passing state to preact component将状态传递给 preact 组件
【发布时间】:2018-03-09 00:31:13
【问题描述】:

我有一个新人要做出反应/预演。我有一个从 API 获取天气预报的简单应用程序,我希望将此数据传递给图表组件(预图表)。我遇到的问题是当这个图表被渲染时,数据还没有被提取并且我得到类型错误,因为我已经在尝试处理它了。我看到另一个问题,其中最佳答案建议在尚未评估父组件的状态时有条件地将 null 而不是组件分配给变量。

在父组件中,我有以下方法设置要传递的状态(由父组件的构造函数调用):

parseHourly = (parsed_json) => {
    for (let i = 0; i < 7; i++) {
        var h = parsed_json['hourly_forecast'][i]['FCTTIME']['hour'];
        var t = parsed_json['hourly_forecast'][i]['temp']['metric'];
        var pair = {hour: h, temperature: t};
        this.state.temps.push(pair);
    }
}

这是我创建图表的父级渲染方法:

render() {
    let myChart;
    if(this.state.temps) {
        myChart = <Chart temps={this.state.temps}/>
    } else {
        myChart = null
    }

    return (
        <div class={ style.container }>
            ...
            { myChart }
            ...
        </div>
    );
}

在 Chart 组件中,我尝试在 render() 方法中直接访问 this.props.temps,但最终得到的值为 undefined。 我究竟做错了什么?非常感谢您的帮助。

【问题讨论】:

  • 您在parseHourly 函数中没有使用setState 是否有原因?它应该是这样的:this.setState(state =&gt; ({ temps: [...state.temps, pair] }))。这只是一个猜测,如果这最终解决了问题,我会写一个答案
  • @kingdaro 老实说,我不太确定。在构造函数中,我做了this.state.temps = []; 我正在遵循我给出的样板代码,因为我还是一个全新的人。使用setState()和直接设置字段有区别吗?
  • 使用 setState() 是通知 React/Preact 它需要执行重新渲染的正确方法。直接设置或改变变量不会做任何事情,因为 react 不会以这种方式观察它们的变化。
  • 此时,是否还需要if(this.state.temps){...}?顺便说一句,感谢您的回复,@FisNaN 已经提交了答案,但这仍然很有帮助。
  • 只要它始终是一个数组,您可能可以将其删除。当然:)

标签: javascript reactjs asynchronous ecmascript-6 preact


【解决方案1】:

您需要使用setState 函数,创建一个先前状态的副本,然后将新项目推入。
请参考 React 生命周期文档:https://reactjs.org/docs/react-component.html#setstate

下面的代码是如何在您的情况下设置状态。但是,你必须把这个函数放在 React 可以更新状态的地方:

parseHourly = (parsed_json) = > {
  const bufferTemps = JSON.parse(JSON.stringify(this.state.temps));
  for (let i = 0; i < 7; i++) {
    const h = parsed_json['hourly_forecast'][i]['FCTTIME']['hour'];
    const t = parsed_json['hourly_forecast'][i]['temp']['metric'];
    const pair = {
      hour: h,
      temperature: t
    };
    bufferTemps.push(pair);
  }
  this.setState({
    temps: bufferTemps
  });
}

注意:
const bufferTemps = [...this.state.temps]不会为每个项目创建一个深拷贝,它不应该这样做this.state.temps.push(pair)
为了解决这个问题,我使用JSON.parse(JSON.stringify(this.state.temps)) 来创建一个深度克隆。

【讨论】:

  • 它在父类中运行良好,但是当我实例化图表时:&lt;Chart temps={this.state.temps}/&gt; 并尝试在图表构造函数中alert(props.temps),我得到一个空的警报窗口。
  • 如果您查看我附加的链接。 constuctor 在 React 生命周期中位于 componentWillMount 之前您可以尝试从 componentDidMount 尝试 console.log 并查看发生了什么。
  • (我删除了之前的评论)它记录了一个空数组。
  • @JanParzydło 如果你创建一个代码框,我可能会帮助你codesandbox.io/s/new
  • 感谢您的努力,但要压缩项目并让它在那里运行对我来说会很复杂。同样,我是一个初学者,我正在构建一些我不完全理解的自定义样板代码。
【解决方案2】:

您似乎正在初始化this.state.temps = [],但在您的render() 方法中,您正在检查if (this.state.temps)。 JS中的空数组是真的(==true),所以检查总会通过。

试试这个:

class Parent extends Component {
  constructor() {
    super();
    this.state.temps = [];
  }
  // ... etc ...
  render() {
    let myChart
    // if we have any temperatures:
    if (this.state.temps.length>0) {
      myChart = <Chart temps={this.state.temps} />
    }
    return <div class={style.container}>{myChart}</div>
  }
}

class Chart extends Component {
  render() {
    // now we know temps will be an Array of 1 or more items:
    console.log(this.props.temps)
  }
}

【讨论】:

    猜你喜欢
    • 2018-01-27
    • 2016-08-17
    • 2017-08-12
    • 2021-01-03
    • 2019-01-20
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 2019-09-18
    相关资源
    最近更新 更多