Ouderstate wijzigen in kindcomponent in React
In de vorige les werd de state met gegevens opgeslagen in de oudercomponent, en de kindcomponenten ontvingen deze gegevens als props.
Stel dat we nu onze producten willen wijzigen.
Laten we bijvoorbeeld een knop maken die
ons product in het winkelwagentje plaatst. Laten we eerst
een veld inCart toevoegen aan onze array met producten,
dat aangeeft of het product
in het winkelwagentje zit of niet:
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},
];
In de component Products voegen we nog een attribuut
inCart toe aan de tag met het product:
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>;
}
Laten we in de kindcomponent Product
een weergave maken van de informatie over het winkelwagentje en een knop
voor toevoegen aan het winkelwagentje:
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>;
}
Laten we de toevoeging implementeren
Volgens de regels van React mag een component
zijn props niet wijzigen. Dit betekent dat
een kindcomponent zichzelf niet
in het winkelwagentje kan plaatsen door de prop inCart te wijzigen.
Dat is niet correct.
De correcte manier is om de oudercomponent te vragen
zijn state prods te wijzigen, door
een bepaald product in het winkelwagentje te plaatsen.
Laten we kijken hoe dat wordt gedaan.
Laten we in de oudercomponent een functie addToCart maken,
die een id van een product als parameter accepteert
en voor dat product de eigenschap inCart wijzigt
naar true:
function addToCart(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.inCart = true;
}
return prod;
}));
}
Laten we aan de product-tag een attribuut toevoegen, waarin we
onze gemaakte functie doorgeven, en ook
een attribuut, waarin we de id van het product doorgeven:
const items = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name ={prod.name}
cost ={prod.cost}
inCart ={prod.inCart}
addToCart={addToCart}
/>;
});
Zoals je ziet, kunnen aan de props van componenten niet alleen gegevens worden doorgegeven, maar ook functies.
De uiteindelijke code van de component Products wordt
als volgt:
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>;
}
Nu is de functie addToCart beschikbaar in de kindcomponent.
Laten we deze functie aanroepen
bij een klik op de knop, en de id van het product
als parameter doorgeven:
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>;
}
Het resultaat is dat bij een klik op de knop in de afstammeling de functie van de ouder wordt aangeroepen, die de state van de ouder zal wijzigen. Het wijzigen van de state van de ouder zal een herrender veroorzaken en ons product opnieuw tekenen, waarbij de gewijzigde prop wordt doorgegeven.
Neem de component User uit de vorige
les. Zorg ervoor dat er een knop in verschijnt
om de gebruiker te verbannen.