ReactJs: как предотвратить повторный рендеринг componentWillUpdate несколько раз

Я создаю простое приложение 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.info(data);
        if (data === "success") {
          console.info("Yay");
        }
      })
      .catch(err => {
        console.info(err);
      });
    console.info(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
    });
  };

Вам нужно вызвать this.setState() в addBtn, когда у вас есть данные, вместо повторного вызова this.displayData(). Обновление состояния с помощью setState вызовет повторный рендеринг. В настоящее время вы планируете новое обновление во время обновления, что приведет к бесконечному циклу обновлений. Также обратите внимание, что componentWillUpdate устарела и больше не должны использоваться.

trixn 05.04.2019 12:04

Я пробовал это, но он все еще не показывает данные на экране.

user10900191 05.04.2019 12:08

Тогда вы не правильно сделали. Пожалуйста, добавьте свой метод render() и как и куда вы звонили setState.

trixn 05.04.2019 12:09

Вы можете вызвать this.displayData() при успешном обратном вызове метода fetch call in addBtn.

Jyothi Babu Araja 05.04.2019 12:17
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
4
598
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Для этого нужно сначала понять, как работают componentDidMount и componentWillUpdate в React. Они методы жизненного цикла реакции.

componentDidMount вызывается после монтирования компонента. Он вызывается только один раз и никогда не вызывается снова, если его не размонтировать и не смонтировать снова.

componentWillUpdate вызывается каждый раз, когда изменяется состояние и происходит повторный рендеринг.

Как прокомментировал @trixn: Вам нужно вызвать this.setState() в addBtn, когда у вас есть данные, вместо многократного вызова this.displayData()

Итак, мне следует размонтировать, а затем снова смонтировать?

user10900191 05.04.2019 12:08

componentDidMount — это правильное место для загрузки в первый раз, а затем, после создания нового Todo, вам нужно обновить список сразу после завершения запроса СООБЩЕНИЕ.

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

Чтобы улучшить производительность, вы должны вернуть новую запись Todo после POST, поэтому вы только помещаете ее в список userArray в состоянии, нет необходимости снова получать весь список

Очень ценю

user10900191 05.04.2019 12:24
Ответ принят как подходящий

Итак, давайте попробуем разобраться, почему обращений к серверу было много.

Когда создается componentDidMount, вы вызываете displayData, который затем устанавливает состояние. Как только вызывается 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.info(data);
                if (data === 'success') {
                    this.displayData();
                }
            })
            .catch(err => {
                console.info(err);
            });
    };

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

По сути, я удалил вызов displayData в componentDidUpdate, а затем вызвал displayData, когда вызов ApI был успешным.

Все дали правильный ответ, Но есть малюсенькая ошибка.

Вы должны вызвать displayData() вне if condition

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

Другие вопросы по теме