React this.setState не обновляет мое значение, при изменении firebase отображаются

У меня проблема с кодом. Я пытаюсь делать заметки в react + fireabse. Добавление заметок в fireabse работает, и setState показывает их, но если я хочу изменить значение заметки, второй setState не меняет его, но в firebase заметка изменит свое значение.

Вот мой код

constructor() {
 super(); 
 this.app = firebase.initializeApp(DB_CONFIG);
 this.database = this.app.database().ref().child('notes');

 this.state = {
  notes: [],
 };
}

componentDidMount() {
 this.database.on('child_added', snap => {
   this.state.notes.push(new Note(snap.key, snap.val().noteContent));
   this.setState({
     notes: this.state.notes
   });
 });

 this.database.on('child_changed', snap => {
   this.state.notes.forEach(note => {
     if (snap.key === note.id) {
       note.id = snap.key;
       note.noteContent = snap.val().noteContent;
     }
   });
  this.setState({
     notes: this.state.notes,
   });
 });
}

addNote(note) {
 this.database.push().set({
   noteContent: note,
 });
}

changeNote(id, note) {
 this.database.child(id).update({
   noteContent: note,
 });
}

render() {
return (
  <div>

    <div> {
      this.state.notes.map(note => {
          return (
            <NoteComponent noteContent = {note.noteContent} 
              noteId = {note.id} 
              key = {note.id}
              changeNote = {this.changeNote.bind(this)}>
            </NoteComponent>
          )
        })
      }
  </div>

  <div>

  </div>
    <NoteFormComponent 
      addNote = {this.addNote.bind(this)}>
    </NoteFormComponent>
  </div>
);

}

Спасибо за помощь.

Поведение ключевого слова "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) для оценки ваших знаний,...
1
0
703
2

Ответы 2

Проблемные строки:

this.state.notes.push(new Note(snap.key, snap.val().noteContent));

или же

 this.state.notes.forEach(note => {
     if (snap.key === note.id) {
       note.id = snap.key;
       note.noteContent = snap.val().noteContent;
     }
   });
  this.setState({
     notes: this.state.notes,
   });

Вы не можете изменить значение состояния таким образом. Вы ДОЛЖНЫ использовать setState. Чтобы это исправить, вам необходимо:

  1. скопируйте (deepclone) массив состояний (вы должны использовать ImmutableJS, но это будет работать для тестирования: const copiedArray = JSON.parse(JSON.stringify(array)))
  2. Внесите изменения в скопированный массив copiedArray.
  3. setState('notes', copiedArray)

Другие предложения:

Я бы посоветовал вам сделать следующее. Изолируйте слой базы огня от слоя просмотра. Не рекомендуется совмещать обязанности компонента с связью с базой данных. После того, как вы это сделаете. вы передадите список примечаний извне компонента. И любой метод, работающий с базой данных (firebase в вашем случае также будет параметром).

// Notes Container
    const notes = FireBaseConnector.getNotes();
    const {
        add,
        edit,
        delete,
    } = FireBaseConnector

    <Notes notes = {notes}
         onAdd = {add}
         onEdit = {edit}
         onRemove = {delete}
    />

Вы должны сделать что-то вроде этого:

const newNotes = [...this.state.notes]
const newNode = {
  id: snap.key,
  noteContent: snap.val().noteContent,
}
newNotes.push(newNode)
this.setState({
     notes: newNotes,
});

вы не можете просто нажать, вам нужно заменить массив узлов новым массивом. необходимо соблюдать неизменяемость, чтобы сказать, как реагировать на повторную визуализацию

Спасибо за ваш отзыв, но в вашем коде я добавляю новый элемент и хочу только изменить выбранный узел noteContent, как это происходит в firebase, но this.setState не изменяет noteContent, после обновления страницы данные будут загружены из firebase и будет выглядеть так, как хочет

PepeFiStach 17.05.2018 14:17

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