Винаги сме приемали да не променяме директно състоянието в React, било то локално състояние в рамките на компонентите или редукционното състояние по отношение на редукторите. Мислили ли сте за това, защо е така? Тази статия ще се опита да подобри знанията ни защо мутацията на състояние е табу, ако не искате да имате код с грешки в производството.

Първо, нека разберем някои основни понятия относно типовете данни на Javascript.

Примитивни типове данни:

Има 5 примитивни типа даннив Javascript, които са Strings, Numbers, Booleans, Nulls и Undefined и те се предават по стойност, когато се копират или преназначават. Това означава, че се създава ново пространство в паметта за всяка преназначена стойност. Вижте примера по-долу.

let a = "obinna";
let b = a;
console.log(a) --> "obinna"
console.log(b) --> "obinna"

Това означава, че на a е присвоено пространство в паметта и на b също е присвоено пространство в паметта въз основа на техните стойности и промяна в стойността на a няма да повлияе на стойността на b. Вижте например по-долу.

let a = "obinna";
let b = a;
a = "segun";
console.log(a) --> "segun"
console.log(b) --> "obinna"

От илюстрацията по-горе ще забележим, че промяна в a няма ефект върху b.

Непримитивни типове данни

Някои примери за непримитивни типове данни са Objects, Functions и Arrays. Тези типове данни се предават от reference и това ще бъде обяснено по-долу.

let original = {value: "ahmed"}
let copied = original;
console.log(original) --> {value: "ahmed"}
console.log(copied) --> {value: "ahmed"}

Ако решим да променим обекта original, като променим стойността на original.value, забелязваме, че copied.value също ще се промени.

let original = {value: "ahmed"}
let copied = original;
original.value = "moses";
console.log(original) --> {value: "moses"}
console.log(copied) --> {value: "moses"}

Това поведение се наблюдава поради начина, по който Javascript записва своите непримитивни стойности в променливи. Стойностите, които трябва да бъдат записани в паметта, се записват, адресът към това място в паметта също се записва и накрая всички променливи се препращат към адреса в местоположението.

Така че в този случай, когато обектът original е преназначен на нова променлива copied, той не създава отново нов адрес в паметта, нито създава нов обект в паметта. Това, което прави, е да препраща новата променлива copied към същия обект в паметта. Следователно, промяна в която и да е от променливите original или copied ефективно ще промени стойността в паметта, която ще се вижда както от copied , така и от original. Това не е ли интересно?

Повече подробности можете да намерите в много добра статия от Arnav Aggarwal

И така, какво общо има всичко това с неизменността в React?

И така, Реагирайте, тъй като JS рамката рендерира своите компоненти, ако props или state на този компонент се промени. В тази статия ще използваме „куки за реакция“, за да илюстрираме нашия пример, докато използваме object като първоначално състояние (както се вижда в useState по-долу), за да илюстрираме правилно ефекта от мутирането на състояние.

import React, { useState } from 'react';

function Example() {
const [name, setName] = useState({name: 'Aisha'}});
  return (
    <div>
      <p>You changed the Name to {name.name}</p>
      <button onClick={() => setName({name: 'Wale'})}>
        Change name
      </button>
    </div>
  );
}

От примера по-горе забелязваме, че състоянието name се променя чрез използване на функция setName, произведена от куката useState. Следователно, ако name се промени след щракване върху бутона, компонентът се изобразява отново, за да покаже новото име Wale.

Човек може да се изкуши да промени състоянието на name като направи това:

name.name = 'Wale';

Технически това е един от начините за промяна на свойството на Javascript обект, но в случай на React това не се препоръчва като адрес на променливата name не се променя. Променя стойността на name.name в паметта, но тъй като реакцията не забелязва промяна в адреса на паметта, не я разпознава като промяна. Следователно компонентът не се изобразява повторно.

Ако изобразим отново този компонент по някакъв друг начин (правилна промяна на състоянието или реквизитите), неговото повторно изобразяване ще покаже, че стойността е променена и ще покаже Wale.

Това може да причини грешка във вашата кодова база и ще бъде много, много трудно за проследяване, така че е силно препоръчително да използвате setState в компонентите, базирани на клас и setter от useState в куките на React.

Ще се радвам да видя принос в секцията за коментари относно това как тази статия може да бъде подобрена или всеки въпрос относно това, за да можем да учим заедно.

Благодаря момчета.