Mam problem ze zrozumieniem useState w poniższym kodzie. Kiedy przykładowo const [x, setX] = useState([])
, to przy pierwszym renderze zmienna x
jest pustą tablicą, ale po zmianie wartości za pomocą setX
, przy kolejnym renderze komponentu, useState([]) - argument (czyli pusta tablica) jest ignorowany i zastępowany nową wartością. Tak jak w dokumentacji: https://pl.reactjs.org/docs/hooks-rules.html#explanation
Ale co w sytuacji, gdy argumentem jest funkcja, która jest od razu wywoływana i zapisuje klucz z wartością do localStorage, tak jak poniżej.
Przy pierwszym renderze zwracana jest pusta tablica (ponieważ zmienna list
= null
). Po kliknięciu Submit i wywołaniu setIgredients
oraz ponownym wyrenderowaniu komponentu, getLocalStorage()
nie jest pominięty, tylko jeszcze raz się wywołuje. Czyli ostatecznie co jest podmieniane przy kolejnym renderze dla igredients
: wartość zwrócona z getLocalStorage()
czy [...igredients, newProduct]
?
Snippet: https://codesandbox.io/embed/quizzical-saha-m6900?fontsize=14&hidenavigation=1&theme=dark
import React, { useEffect, useState } from "react";
const getLocalStorage = () => {
let list = localStorage.getItem("list");
// console.log(list)
if (list) {
console.log(1);
return JSON.parse(localStorage.getItem("list"));
} else {
return [];
}
};
const GroceryBud = () => {
const [product, setProduct] = useState("");
const [igredients, setIgredients] = useState(getLocalStorage()); // <---
const [error, setError] = useState("");
const [success, setSuccess] = useState("");
const [btnType, setBtnType] = useState("Submit");
const handleChange = (e) => {
setProduct(e.target.value);
};
const messageHandler = (message, text) => {
message(text);
setTimeout(() => {
message("");
}, 2500);
};
const handleSubmit = (e) => {
e.preventDefault();
if (product) {
if (btnType === "Submit") {
const newProduct = { id: new Date().getTime(), product };
setIgredients([...igredients, newProduct]);
setProduct("");
messageHandler(setSuccess, "Item Added To The List");
}
} else {
messageHandler(setError, "Please Enter Value");
}
};
useEffect(() => {
localStorage.setItem("list", JSON.stringify(igredients));
}, [igredients]);
return (
<div id="wrapper">
{error && <p className="warning">{error}</p>}
{success && <p className="success">{success}</p>}
<h2>Grocery Bud</h2>
<form>
<input
type="text"
className="product-field"
placeholder="e.g. eggs"
value={product}
onChange={handleChange}
/>
<button type="submit" className="submit" onClick={handleSubmit}>
{btnType}
</button>
</form>
<div className="igredients">
{igredients.map((item, index) => {
const { id, product } = item;
return (
<article key={id}>
<p>{product}</p>
</article>
);
})}
</div>
</div>
);
};