console.log(1 === 1); // true
console.log('a' === 'a'); // true
console.log(true === true); // true
console.log(undefined === undefined); // true
console.log(Symbol('a').toString() === Symbol('a').toString()); // true
console.log('a' === 'a'); // true
console.log(true === true); // true
console.log(undefined === undefined); // true
console.log(Symbol('a').toString() === Symbol('a').toString()); // true
Czyli jeśli wartość props lub state zmieni się z 1 na 2 to komponent wie, że ma się zrerenderować. Proste.
A jednak, nie do końca. Wszystko co nie jest prymitywem w JS (jest to pewne uproszczenie, będzie osobny wpis na ten temat) jest obiektem. A obiekty nie są przekazywane przez wartość a przez referencję. Innymi słowy JS umieszcza utworzony obiekt gdzieś w pamięci i posługuje się adresem tego obiektu a nie nim samym. Każde utworzenie obiektu tworzy nową referencję.
const a = { id: 1 };
const b = { id: 1 };
console.log(a === a); // true
console.log(a === b); // false
console.log(Object.is(a, a)); // true console.log(Object.is(a, b)); // false
const b = { id: 1 };
console.log(a === a); // true
console.log(a === b); // false
console.log(Object.is(a, a)); // true console.log(Object.is(a, b)); // false
Czyli nawet dwa identyczne obiekty mają dwie różne referencje, więc nie da się ich łatwo porównać. React do porównywania obiektów używa Object.is().
Dlatego, gdy zmieniamy jakąś wartość w obiekcie, powinniśmy stworzyć nową referencję, żeby react zauważył zmianę, na przykład tak:
const [formData, setFormData] = useState({});
function handleChange(evt) {
const id = evt.target.id;
const value = evt.target.value;
const formCopy = { ...formData };
formCopy[id] = value;
setFormData(formCopy);
}
function handleChange(evt) {
const id = evt.target.id;
const value = evt.target.value;
const formCopy = { ...formData };
formCopy[id] = value;
setFormData(formCopy);
}
Alternatywnym sposobem może być używanie biblioteki jak immutable.js aby każda zmiana w obiekcie zwracała nową referencję.
Brak komentarzy:
Prześlij komentarz