Oi Bruno!
Realmente, o state
não é atualizado imediatamente, a mudança ocorrerá somente quando o componente for renderizado novamente. Isso acontece porque tanto o state
quanto o setState
são imutáveis, ou seja, não é possível alterar o valor deles uma vez declarados. Quando você ver sobre os hooks, observe que eles são declarados como const
. Isso é feito para que os objetos manipulados pelo React (componentes e seus states) não mudem e causem efeitos colaterais. Apesar de parecer que o state
mudou, quando o componente é renderizado novamente, um novo state
é criado, contendo o valor chamado pelo setState
que causou a renderização.
Agora vamos para o seu código: Os console.log()
que aparecem estão "atrasados" mas o state
do componente está sim com os valores atualizados.
Vamos supor que o state
comece como um array vazio. Quando criarNota()
é chamado da primeira vez, uma nova nota é criada, depois ela é adicionada ao novoState
. O primeiro console.log()
printa o this.state
atual que é nulo. O segundo também printará a mesma coisa, pois o this.state
é imutável como dito acima, o seu valor só será atualizado na próxima renderização, que acontece pois setState
é executado.
Quando a próxima renderização ocorre, this.state
recebe o valor passado para o setState
da renderização anterior, ou seja, o this.state
recebe novoEstado
que contém uma nota. Porém quando a função criaNota
é executada, o primeiro console.log
printa o estado atual, e o segundo a mesma coisa pelo motivo do parágrafo anterior. Uma nova renderização é causada pelo setState
, um novo estado é criado e assim por diante.
Então apesar dos console.log
estarem atrasados, o estado do componente está sim atualizado. Teste isso adicionando as seguintes linhas de código que utiliza o último item do array do state
<h1>{this.state.notas[this.state.notas.length - 1].titulo}</h1>
<p>{this.state.notas[this.state.notas.length - 1].texto}</p>
O código acima pode ajudar a entender sua segunda dúvida. Quando a linha a seguir é executada
const novoArrayNotas = [...this.state.notas, novaNota];
estamos adicionando um objeto com as propriedades titulo
e texto
ao array novoArrayNotas
. Por ser um objeto, é possível acessar suas propriedades com a sintaxe objeto.propriedade
, como nota.texto
ou nota.titulo
. Caso a novaNota
fosse declarada como um array isso não seria possível, pois os elementos teriam que ser acessados com nota[0]
e nota[1]
e isso quebraria o código, pois o restante dos objetos teriam as propriedades texto
e titulo
mas o novaNota
não. Ou seja, ao tentar executar o comando novaNota.titulo
teriamos como retorno undefined
.
Essas perguntas foram bem complicadas, então não se preocupe caso não entenda imediatamente. Caso surjam novas dúvidas ou você queira outra explicação, poste aqui!
Parabéns por ter feito essas reflexões! Elas são muito importantes para um bom aprendizado.
Espero ter ajudado.