渲染方法在React中触发2次

时间:2016-10-29 06:28:16

标签: javascript node.js reactjs socket.io react-router

我有一个房间,我有一些消息。所以模型是

{
  createdAt: Date,
  messages: [String]
}

我用

取了我的房间
class Room extends React.Component {
  constructor(props) {
    super(props);
    this.state = { room: {} };
  }

  componentDidMount() {
    this.fetchRoom();
  }

  componentDidUpdate(prevProps) {
    let oldId = prevProps.params.roomId
    let newId = this.props.params.roomId
    if (newId !== oldId) {
      this.fetchRoom();
    }
  }

  componentWillUnmount() {
    this.ignoreLastFetch = true;
  }

  fetchRoom() {
    if (!this.ignoreLastFetch) {
      const roomId = this.props.params.roomId;
      socket.emit('get room', roomId, room => {
        this.setState({ room: room });
      });
    }
  }

  render() {
    console.log(this.state.room.messages); // debug

    const roomId = this.state.room._id;
    return (
      <div>
        <h2>Id: {roomId}</h2>
        <p>Created at: {this.state.room.createdAt}</p>
        <h2>Messages</h2>
        <Messages roomId={roomId} messages={this.state.room.messages} />
      </div>
    );
  }
}

问题是render()在之前被称为我已经取出房间,之后我已经取出房间,因此它会导致2次通话。

我不能等到render才取出房间,因为我不在乎看空房间吗?

似乎因为我使用<Messages roomId={roomId} messages={this.state.room.messages} />,它会发送一个空数组的消息。如果我使用render()console.log(this.state.room.messages)方法中调试,它首先打印undefined,然后打印消息数组(即2个调用)。

2 个答案:

答案 0 :(得分:2)

在安装组件后将调用方法render,但在获得所需数据之前,有一种方法不会呈现组件。 React documentation定义了如何解决这个问题:

  

您还可以返回null或false以表示您不想要   任何渲染的东西。

让我们在渲染方法中利用这一点:

render() {
    // check if the room is set
    if(!this.state.room){
        // room is not set, return null so that nothing is rendered
        return null;
    }

    // happy path - render the room
    const roomId = this.state.room._id;
    return (
      <div>
        <h2>Id: {roomId}</h2>
        <p>Created at: {this.state.room.createdAt}</p>
        <h2>Messages</h2>
        <Messages roomId={roomId} messages={this.state.room.messages} />
      </div>
    );
  }

答案 1 :(得分:0)

您应该将此逻辑放在“shouldComponentUpdate”中,而不是放在Render方法中。 render方法应该是纯粹的,你不应该在其中放置任何逻辑。从Component返回null也可能对Virtual Dom有站点效果。