未捕获(按承诺)TypeError:无法读取null的属性“ red”

时间:2019-03-18 07:15:58

标签: node.js reactjs socket.io

import React from "react";
import io from "socket.io-client";

class TrafficLight extends React.PureComponent {
  state = { lamp: null, currentcolor: "red" };

  // turnLampOn event handler
  turnLampOn = async () => {
    while (true) {

//如果我尝试在Heroku上的生产环境中运行此应用,则会在此处显示Null错误

// currentcolor=red wait 'red' ms and enable 'green'

      await this.waitSomeSeconds("green", this.state.lamp.red);
      // currentcolor=green wait 'green' ms and enable 'yellow'
      await this.waitSomeSeconds("yellow", this.state.lamp.green);
      // currentcolor=yellow wait 'yellow' ms and enable 'red'
      await this.waitSomeSeconds("red", this.state.lamp.yellow);
    }
  };

  waitSomeSeconds = (color, wait) => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log(
          this.props.street +
            ": from " +
            this.state.currentcolor +
            " to " +
            color +
            ", wait=" +
            wait
        );
        this.setState({ currentcolor: color });
        resolve();
      }, wait);
    });
  };

  componentDidMount = async () => {
    // connect to server
    //let socket = io.connect("localhost:5000", { forceNew: true });
    // send join message to server, pass a payload to it (street name specified via props)
    // connect to server on Heroku cloud
    const socket = io.connect();

    socket.emit("join", { streetName: this.props.street }, err => {});
    // wait on 'turnLampOn'
    socket.on("turnLampOn", lampData => {
      console.log("turnLampOn", lampData);
      // Set new lamp data and start trafficlight
      if (this.state.lamp === null) {
        this.setState({ lamp: lampData });

//当应用程序尝试执行此方法时,将出现空值。

    this.turnLampOn();
  }
});

};

  // Get current color helper
  getColor = color => (this.state.currentcolor === color ? color : "white");

  render() {
    return (
      <div className="light">
        <div
          className="lamp"
          style={{ backgroundColor: this.getColor("red"), margin: ".5rem" }}
        />
        <div
          className="lamp"
          style={{ backgroundColor: this.getColor("yellow"), margin: ".5rem" }}
        />
        <div
          className="lamp"
          style={{ backgroundColor: this.getColor("green"), margin: ".5rem" }}
        />
        <div style={{ textAlign: "center", fontName: "Helvetica" }}>
          {this.props.street}
        </div>
      </div>
    );
  }
}

export default TrafficLight;

此应用在开发模式下运行良好,错误在生产环境中发生。 该应用程序具有一个Node.js服务器,其中包含用于建立连接的sockect.io

1 个答案:

答案 0 :(得分:1)

React的setState函数是异步的,不会立即更新状态。根据文档

  

将setState()视为请求而不是立即命令来更新组件。为了获得更好的感知性能,React可能会延迟它,然后在一次通过中更新几个组件。 React不能保证状态更改会立即应用。

     

setState()并不总是立即更新组件。它可能会批量更新或将更新推迟到以后。这使得在调用setState()之后立即读取this.state可能是一个陷阱。而是使用componentDidUpdate或setState回调(setState(updater,callback)),确保在应用更新后均能触发这两种方法。如果需要基于先前的状态来设置状态,请阅读以下有关updater参数的信息。

有关更多信息,请查看here

要解决您的问题,请在before.plot.new的回调中调用turnLampOn方法

setState