Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

React Retorna apenas o ultimo elemento de um forEach, como resolver?

Olá, colegas e instrutores. Na minha função deveria ser retornado uma função para criar as notas, porém apenas funciona com a última. É uma extensão do código do curso de React:

  createNote(title, date ,text) {
    const newNote = {title, date ,text}
    const newNotesArray = [...this.state.notes,newNote]
    const newStatea = {
      notes: newNotesArray
    }
    this.setState(newStatea)
  }

_

createNoteOfLocalStorage(event){
    const CreatedTasks = JSON.parse(localStorage.getItem('task')) || []


    CreatedTasks.forEach((el)=>{
      console.log(...el)
      this.createNote(...el)
    })

no console retorna: HELLO THERE October 11th 2021, 11:18 HELLO THERE 10000101 October 11th 2021, 10:26 100010100101

porém na tela apenas retorna o ultimo.

Para a fase de testes chamo a função por um botão, mesmo:

caso necessário meu o projeto no github com todo o código:

https://github.com/Ryan-R-C/React-Note-Project

#

Obrigado desde já

2 respostas
solução!

Olá, Ryan! Tudo bem?

Recomendo que você dê uma lida nessa parte da documentação do React, porque acredito que seja esse o problema.

Para cada elemento do forEach você chama o this.setState, criando uma nova array com os elementos prévios e adicionando ao fim o novo elemento, certo? O problema é que, pode acontecer o seguinte:

- 1o elemento (CreatedTasks[0]) -> chama this.setState que não atualiza o estado imediatamente;
- 2o elemento (CreatedTasks[0]) -> chama this.setState, mas o estado ainda é [], e de novo, não atualiza imediatamente;
...
- Último elemento (CreatedTasks[CreatedTasks.length - 1]) -> chama this.setState, o estado ainda é [], como é a última chamada, o estado será atualizado eventualmente com esse valor passado.

Então, de fato, a variável é atualizada, mas o estado da aplicação não reflete isso e acaba dessíncronizado.

É por isso que React incentiva tanto o uso de programação funcional. Tendo em mente esse paradigma, o seu código funcionaria melhor da seguinte forma:

  • A createNote deve apenas criar uma nota, ela está fazendo duas coisas diferentes (criando uma nota, e atualizando o array). Esse é o efeito colateral que está prejudicando o seu código.
// como essa operação é muito simples, também pode ser feita manualmente (const newNote = { title, date, text }))
// no próprio createNoteOfLocalStorage
createNote(title, date ,text) {
    return {title, date ,text}
}
  • Na createNoteOfLocalStorage você primeiro cria a nova array de tarefas, depois atualiza o estado apenas uma vez.
createNoteOfLocalStorage(event) {
    const CreatedTasks = JSON.parse(localStorage.getItem('task')) || []


    const localStorageTasks = CreatedTasks.map((el)=>{
      console.log(...el)
      this.createNote(...el)
    }) // o map vai retornar uma nova nota para cada elemento

    const notes = [...this.state.notes, ...localStorageTasks]
    this.setState({ notes })
}

Obs: A createNoteOfLocalStorage poderia ter um nome melhor, como loadNotesFromLocalStorage, assim fica mais claro que ela carrega várias notas e atualiza o estado. O nome atual dá a entender que ela só cria uma nota a partir do Local Storage

E dessa maneira seu código vai atualizar o estado apenas uma vez, o que melhora a performance e também evita efeitos colaterais inesperados (como o que você encontrou).

Espero que ajude!

Muito obrigado, Leonardo! Às vezes é melhor ir direto na fonte. Muito obrigado