【问题标题】:Render method firing 2 times in React渲染方法在 React 中触发 2 次
【发布时间】:2017-03-12 00:43:30
【问题描述】:

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

{
  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() 都被称为before我取房间和after我取房间,所以它导致2个电话。

因为我不在乎看到一个空房间,所以我不能等到我把房间拿走后再开render吗?

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

【问题讨论】:

  • 在 react 中,render 会在你调用 setState 之后(或者之前?)组件被安装之后立即调用。这是正常的。

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


【解决方案1】:

方法render会在组件挂载后被调用,但是有一种方法在你得到你需要的数据之前不渲染组件。 React documentation 定义了如何解决这个问题:

你也可以返回 null 或 false 来表示你不想要 任何渲染。

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

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>
    );
  }

【讨论】:

    【解决方案2】:

    您应该将此逻辑放在“shouldComponentUpdate”中,而不是在 Render 方法中。渲染方法应该是纯的,你不应该在其中放置任何逻辑。此外,从 Component 返回 null 可能会对 Virtual Dom 产生站点影响。

    【讨论】:

    • 我应该在shouldComponentUpdate而不是render中放置什么逻辑?除了返回null,还有其他选择吗?
    • 如果调用渲染方法,shouldComponentUpdate 返回true。这使您可以对以前的道具执行简单和复杂的道具检查。如果您知道更改需要写入“真实”dom,这允许您返回“true”。这意味着 React 不会过度渲染。
    猜你喜欢
    • 1970-01-01
    • 2021-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-05
    相关资源
    最近更新 更多