Tento článek napsal náš generální ředitel a vývojář Tiago Duarte
Háčky existují již téměř dva roky. Jsou přidány v Reactu v16.8.0 a umožňují vám používat stav a další funkce Reactu, aniž byste museli psát třídu.
V tomto článku se nebudeme moc podrobně zabývat tím, co je háček, jeho syntaxí a tak dále a tak dále. Za tímto účelem můžete navštívit stránku s dokumentací Reactu, kde si myslíme, že tým React odvedl skvělou práci 👍🏾 a nedokázali jsme to vysvětlit lépe.
(Ne)známý problém používání objektů v useState / useEffect hook
To, co nás sem přivádí, je problém/chyba 🐞, se kterou jsme se potýkali, když jsme poprvé začali používat háky, a která může snadno zůstat bez povšimnutí.
Podívejme se na následující příklad:
const { useState } = React;
const Counter = () => {
const [count, setCount] = useState(0);
const [objectCount, setObjectCount] = useState({ count: 0 });
return (
<div>
<h2>Count</h2>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Increase normal count</button>
<h2>Object Count</h2>
<p>You clicked {objectCount.count} times</p>
<button
onClick={() => {
objectCount.count += 1;
setObjectCount(objectCount);
}}
>
Broken increase of the object count
</button>
<br />
<br />
<button
onClick={() =>
setObjectCount({
...objectCount,
count: objectCount.count + 1,
})
}
>
Functioning increase of the object count
</button>
</div>
);
};
ReactDOM.render(<Counter />, document.getElementById('app'));
Připravili jsme tento kodex s příkladem, můžete jej navštívit a pohrát si s ním.
V našem příkladu máme:
-
a
count
státní háček, který ukládá obyčejné číslo -
objectCount
state hook, který ukládá objekt obsahující vlastnost count uvnitř -
"Increase normal count"
tlačítko, které aktualizujecount
Stát. Můžete to ověřit tím, že uvidíte, že se počítadlo aktualizuje ihned po stisknutí tlačítka -
a
"Broken increase of the object count"
tlačítko, které se pokouší aktualizovatobjectCount
, ale nešťastně selže 🙀. Možná si říkáte „naaaaaahhh, to by mělo fungovat…“. Pokračujte a vyzkoušejte to na codepen -
"Functioning increase of the object count"
tlačítko, které správně aktualizujeobjectCount
Stát
Proč stisknout "Broken increase of the object count"
nezvýší okamžitě počet objektů?
Když uživatel stiskne tlačítko, zvýšíme count
vlastnost uvnitř objectCount
objekt a poté zavolejte setObjectCount(objectCount)
.
Problém je v tom, že useState
hook používá přísné porovnání rovnosti k určení, zda má spustit opětovné vykreslení, a nekontroluje, zda se vlastnosti objektu skutečně změnily.
Jinými slovy, hák porovnává (===
) stav „starý“ a „nový“ a dojde k závěru, že se objekt nezměnil a nespustí opětovné vykreslení, což způsobí, že označení počtu objektů zůstane stejné😭.
Možná řešení
Vytvořte a předejte mělkou kopii do setObjectCount
“Functioning increase of the object count”
tlačítko opravuje problém vytvořením a předáním mělké kopie objectCount
na funkci setter.
V zásadě zachovává stejné vlastnosti objektu, ale vytváří novou referenci na objekt, takže porovnání přísné rovnosti háčků určí, že se stav změní, a okamžitě spustí opětovné vykreslení.
Nepoužívejte objekt jako stav
Dalším řešením by bylo jednoduše nepoužívat objekty v useState
háček.
Můžete použít useState
háček pro každou vlastnost objektu. Teoreticky by to byl ideální scénář, ale udělat to může být skličující a časově náročné.
Možná máte důvody k přímému uložení objektu jako stavu. V našem případě jsme získávali data z API a rozhodli jsme se načtený objekt uložit 🤭.
Použijte háček useReducer
Pokud znáte Redux, už víte, jak to funguje, protože je velmi podobný.
useReducer
akceptuje redukci typu (state, action) => newState
a vrátí aktuální stav spárovaný s dispatch
metoda.
Toto je obvykle vhodnější než useState
když máte složitou stavovou logiku, která zahrnuje více dílčích hodnot, nebo když další stav závisí na předchozím.
Použijte immutable.js
Podle dokumentace:
Prakticky řečeno, při použití immutable.js by každá změna objektu ve skutečnosti vytvořila nový objekt. V našem příkladu by to způsobilo, že stavový hák spustí opětovné vykreslení.
Úspora času
Když se tento problém stal mně a Rui Sousovi, strávili jsme, řekl bych, pár hodin hledáním problému. Proto jsme chtěli sdílet tento tip v naději, že vám ušetří čas při ladění!
Pokud máte návrh nebo jiné řešení, než jsou uvedeny, neváhejte a zanechte nám komentář 💬. Jsme velmi přátelští, slibujeme 😇.
Reference
-
Háčky na první pohled
-
Pomocí State Hook
-
Použití efektového háčku
-
MDN — Srovnání rovnosti a stejnosti
-
Porozumění Deep and Shallow Copy v Javascriptu
-
Raquel Pontes mi nedovolila použít původní ilustraci obálky 😢, takže ji nechám zde pro budoucí použití:
Děkujeme za přečtení!
Moc děkujeme za přečtení, moc to pro nás znamená! Nezapomeňte také sledovat Coletiv na Twitteru a LinkedIn jak neustále zveřejňujeme stále více zajímavých článků o různých technologiích.
V případě, že nevíte, Coletiv je studio pro vývoj softwaru z Porta, které se specializuje na vývoj Elixir, webu a aplikací (iOS a Android). Ale děláme všelijaké věci. Postaráme se o návrh UX/UI, vývoj softwaru a dokonce i zabezpečení.
Takže vytvoříme něco společně?