ReactJs:如何防止componentWillUpdate多次重渲染

时间:2019-04-05 09:59:51

标签: javascript reactjs fetch-api

我正在创建一个简单的Todo App,我正在使用componentDidMount来显示数据库中的数据。但是问题是,一旦添加了新数据,数据就会被存储,但是除非刷新,否则数据不会显示在页面上。

然后我遇到了componentDidUpdate。它可以完美工作,但是可以多次渲染,我的意思是它一直在请求服务器检查新数据。 我正在将Express用于后端

那么有人可以告诉我如何预防这种情况吗?还是有更好的解决方案?

这是当前代码:

  class Navbar extends Component {
  state = {
    userArray: [],
    username: "",
    email: ""
  };

  //Storing the Data

  addBtn = e => {
    e.preventDefault();

    var data = {
      username: this.state.username,
      email: this.state.email
    };

    fetch("/user", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data)
    })
      .then(response => {
        if (response.status >= 400) {
          throw new Error("Bad response from server");
        }
        return response.json();
      })
      .then(data => {
        console.log(data);
        if (data === "success") {
          console.log("Yay");
        }
      })
      .catch(err => {
        console.log(err);
      });
    console.log(this.state.userArray);
  };


  componentDidMount() {
    this.displayData();
  }

  componentWillUpdate() {
    this.displayData();
  }

//显示数据

  displayData() {
    fetch("/user")
      .then(data => data.json())
      .then(data => {
        this.setState({
          userArray: data
        });
      });
  }

  //Handling the input values

  logChange = e => {
    this.setState({
      [e.target.name]: e.target.value
    });
  };

4 个答案:

答案 0 :(得分:1)

componentDidMount是第一次加载的正确位置,然后,在创建新的Todo之后,您需要在 POST 请求完成

之后立即刷新列表。
.then(data => {
  console.log(data);
  if (data === "success") {
    console.log("Yay");
    this.displayData();
  }
})

要提高性能,您应该在POST之后返回新的Todo记录,因此您只需将其推入状态为userArray的列表中,而无需再次获取整个列表

答案 1 :(得分:1)

因此,让我们尝试理解为什么服务器有很多呼叫。

创建componentDidMount后,您调用了displayData,然后调用了setState。调用setstate后,它将立即调用componentDidUpdate,该调用再次调用displayData,然后调用setState。然后循环继续进行(可能直到内存用完为止)。

您可以尝试此类:

import React from 'react';

export default class Navbar extends React.Component {
    state = {
        userArray: [],
        username: '',
        email: ''
    };

    componentDidMount() {
        this.displayData();
    }

    addBtn = e => {
        e.preventDefault();

        var data = {
            username: this.state.username,
            email: this.state.email
        };

        fetch('/user', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(data)
        })
            .then(response => {
                if (response.status >= 400) {
                    throw new Error('Bad response from server');
                }
                return response.json();
            })
            .then(data => {
                console.log(data);
                if (data === 'success') {
                    this.displayData();
                }
            })
            .catch(err => {
                console.log(err);
            });
    };

    displayData() {
        fetch('/user')
            .then(data => data.json())
            .then(data => {
                this.setState({
                    userArray: data
                });
            });
    }
}

基本上,我所做的是我删除了对componentDidUpdate中的displayData的调用,然后在ApI调用成功后调用了displayData

答案 2 :(得分:0)

为此,您首先需要了解componentDidMount和componentWillUpdate在React中是如何工作的。 它们是lifecycle methods的反应。

componentDidMount在组件安装后被调用。它只会被调用一次,如果不卸载并再次安装,它将永远不会被调用。

componentWillUpdate每次状态更改和重新呈现都会被调用。

如@trixn所评论: 当您有数据时,需要在addBtn中调用this.setState(),而不是重复调用this.displayData()

答案 3 :(得分:0)

每个人都给出了正确答案,但是有一个小错误。

您应该在displayData()之外拨打if condition

.then(data => {
  console.log(data);
  if (data === "success") {
    console.log("Yay");
  }
   this.displayData();
})