Endre forelderkomponentens state i en barnekomponent i React
I forrige leksjon ble staten med data lagret i forelderkomponenten, og barnekomponentene mottok disse dataene som props.
La oss nå si at vi ønsker å endre våre produkter.
La oss for eksempel lage en knapp som vil
plassere produktet vårt i handlekurven. Til å begynne med
la oss legge til et felt inCart i produktmatrisen vår
som viser om produktet er i handlekurven
eller ikke:
const initProds = [
{id: id(), name: 'product1', cost: 100, inCart: false},
{id: id(), name: 'product2', cost: 200, inCart: false},
{id: id(), name: 'product3', cost: 300, inCart: false},
];
I komponenten Products, la oss legge til enda et attributt
inCart i taggen med produktet:
function Products() {
const [prods, setProds] = useState(initProds);
const items = prods.map(prod => {
return <Product
key ={prod.id}
name ={prod.name}
cost ={prod.cost}
inCart={prod.inCart}
/>;
});
return <div>
{items}
</div>;
}
La oss i barnekomponenten Product
lage en utskrift av informasjon om handlekurven og en knapp
for å legge til i handlekurven:
function Product({ id, name, cost, inCart }) {
return <div>
name: <span>{name}</span>,
cost: <span>{cost}</span>,
<span>{inCart ? 'in cart' : 'not in cart'}</span>
<button>to cart</button>
</div>;
}
Implementerer tillegget
I følge Reacts regler skal en komponent ikke
endre sine props. Dette betyr at
barnekomponenten ikke kan legge seg selv
i handlekurven ved å endre proppen inCart.
Dette er ikke riktig.
Riktig måte er å be forelderkomponenten
endre sin state prods, og legge
det bestemte produktet i handlekurven.
La oss se på hvordan dette gjøres.
I forelderkomponenten lager vi en funksjon addToCart,
som tar id til produktet som parameter
og for dette produktet endrer egenskapen inCart
til true:
function addToCart(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.inCart = true;
}
return prod;
}));
}
I taggen med produktet legger vi til et attributt, der vi
sender funksjonen vi har laget, og også
et attributt der vi sender id til produktet:
const items = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name ={prod.name}
cost ={prod.cost}
inCart ={prod.inCart}
addToCart={addToCart}
/>;
});
Som du ser, kan man i props til komponenter sende ikke bare data, men også funksjoner.
Den endelige koden for komponenten Products blir
følgende:
function Products() {
const [prods, setProds] = useState(initProds);
function addToCart(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.inCart = true;
}
return prod;
}));
}
const items = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name ={prod.name}
cost ={prod.cost}
inCart ={prod.inCart}
addToCart={addToCart}
/>;
});
return <div>
{items}
</div>;
}
Nå vil funksjonen addToCart være tilgjengelig
i barneklassen. La oss kalle denne funksjonen
ved klikk på knappen, og sende den
id til produktet som parameter:
function Product({ id, name, cost, inCart, addToCart }) {
return <div>
name: <span>{name}</span>,
cost: <span>{cost}</span>,
<span>{inCart ? 'in cart' : 'not in cart'}</span>
<button onClick={() => addToCart(id)}>to cart</button>
</div>;
}
Resultatet blir at ved klikk på knappen i barnekomponenten vil forelderens funksjon bli kalt, som vil endre forelderens state. Endring av forelderens state vil utløse en re-rendering og tegne produktet vårt på nytt, og sende den den endrede proppen.
Ta komponenten User fra forrige
leksjon. Gjør slik at en knapp for å banne brukeren vises.