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

问题描述 投票:0回答:4

我正在创建一个简单的Todo应用程序,我使用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
    });
  };
javascript reactjs fetch-api
4个回答
1
投票

所以,让我们试着理解为什么有很多对服务器的调用。

当创建componentDidMount时,你调用displayData,然后设置state。一旦调用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


1
投票

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

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

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


0
投票

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

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

每次状态更改并重新呈现时,都会调用componentWillUpdate。

正如@trixn评论的那样:当你拥有数据而不是重复调用this.displayData()时,你需要在addBtn中调用this.setState()


0
投票

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

你应该在displayData()之外打电话给if condition

.then(data => {
  console.log(data);
  if (data === "success") {
    console.log("Yay");
  }
   this.displayData();
})
© www.soinside.com 2019 - 2024. All rights reserved.