Компонент не перерисовывается после setState ()

В моем коде есть следующий компонент:

class ContactsList extends Component {
   constructor(props) {
      super(props);
      this.state = {
         contactItems: [
            <ContactItem key = "Lena" login = "typeofweb1" name = "Lena" department = "JavaScript Developer" border = "0" />,
            <ContactItem key = "Brian" login = "typeofweb2" name = "Brian" department = "Human Resources" />,
            <ContactItem key = "Rick" login = "typeofweb3" name = "Rick" department = "QA" />
         ]
      };
   }

   render() {
      return (
         <ul className = "list-group list-group-flush container">
            {this.state.contactItems}
            <button type = "button" onClick = {this.addContactItem}>
               Add
            </button>
         </ul>
      );
   }

   addContactItem = () => {
      console.info(this.state.contactItems);
      this.state.contactItems.push(<ContactItem key = "Rick" login = "typeofweb3" name = "Rick" department = "QA" />);
      this.setState({ contactItems: this.state.contactItems });
   };
}

Проблема заключается в том, что компонент не обновляется даже при изменении состояния (я вижу, что в console.info массив contactItems получает новые элементы). Есть проблема с .push (), потому что если просто изменить setState на что-то вроде

this.setState({ contactItems: ["something"]});

тогда все работает правильно.

стандартная проблема изменения существующего объекта

xadm 20.08.2018 11:55

Вы изменяете свой массив. React должен иметь новый массив, чтобы знать, что реквизиты изменились

TryingToImprove 20.08.2018 11:55

почему вы одновременно нажимаете и обновляете состояние ??

anil sidhu 20.08.2018 11:59

Как мне тогда это сделать? addContactItem = () => {this.newArray = this.state.contactItems; this.newArray.push (<ContactItem key = "Rick" login = "typeofweb3" name = "Rick" Department = "QA" />); this.setState ({contactItems: this.newArray}); }; Это не помогает

Łukasz Dębowski 20.08.2018 12:01

это не новый массив, таким образом вы копируете указатель на тот же объект. var dup_array = original_array.slice();

xadm 28.08.2018 12:19
Поведение ключевого слова "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
5
57
2

Ответы 2

Вы не должны изменять состояние в react. Вы можете использовать это так:

addContactItem = () => {
  this.setState({ contactItems: [
    ...this.state.contactItems, // clone the state,
    // then, add new item
    <ContactItem key = "Rick" login = "typeofweb3" name = "Rick" department = "QA" />
   ]
  });
};

когда вам нужно вычислить новое значение состояния на основе некоторого предыдущего значения состояния, вы должны передать функцию обратного вызова методу this.setState вместо прямого чтения из this.state. В противном случае велика вероятность получить несинхронизированные данные. См. Дополнительную информацию в официальной документации: reactjs.org/docs/react-component.html#setstate

falinsky 20.08.2018 18:08

Я точно не знаю почему, но это работает:

class ContactsList extends Component {
   constructor(props) {
      super(props);
      this.state = {
         contactItems: [
            <ContactItem key = "Lena" login = "typeofweb1" name = "Lena" department = "JavaScript Developer" border = "0" />,
            <ContactItem key = "Brian" login = "typeofweb2" name = "Brian" department = "Human Resources" />,
            <ContactItem key = "Rick" login = "typeofweb3" name = "Rick" department = "QA" />
         ]
      };
   }

   render() {
      return (
         <ul className = "list-group list-group-flush container">
            {this.state.contactItems}
            <button type = "button" onClick = {this.addContactItem}>
               Add
            </button>
         </ul>
      );
   }

   addContactItem = () => {
      this.setState(prevState => ({
         contactItems: prevState.contactItems.concat([<ContactItem key = "Rick" login = "typeofweb3" name = "Rick" department = "QA" />])
      }));
   };
}

Может кто-нибудь объяснить мне, почему следующий код работает, а предыдущий - нет?

Да, это сработает, потому что мутации сейчас нет. Потому что вы используете concat, который похож на мой ответ с использованием оператора распространения.

Bhojendra Rauniyar 20.08.2018 12:17

Раньше я пытался скопировать массив и нажать на новый массив, но он все равно не работал, даже несмотря на то, что я обновил состояние с новым массивом, а не с текущим находящимся в состоянии

Łukasz Dębowski 20.08.2018 13:00

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