⊗jsrtPmCpChPS 87 of 112 menu

Modificarea stării părintelui în componenta copil în React

În lecția anterioară, starea cu datele era stocată în componenta părinte, iar componentele copil primeau aceste date sub formă de props.

Să presupunem acum că vrem să ne modificăm produsele. Să facem, de exemplu, un buton care va plasa produsul nostru în coș. Pentru început să adăugăm în matricea noastră cu produse câmpul inCart, care indică dacă produsul este în coș sau nu:

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}, ];

În componenta Products în tag-ul cu produsul să adăugăm încă un atribut inCart:

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>; }

Să în componenta copil Product facem o afișare a informației despre coș și un buton pentru adăugarea în coș:

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>; }

Să implementăm adăugarea

Conform regulilor React o componentă nu ar trebui să-și modifice props-urile. Aceasta înseamnă că componenta copil nu se poate pune singură în coș, modificând prop-ul inCart. Aceasta nu este corect.

Corect ar fi să cerem componentei părinte să-și modifice starea prods, punând un anumit produs în coș.

Să vedem cum se face acest lucru.

În componenta-părinte să facem funcția addToCart, care ca parametru primește id-ul produsului și pentru acel produs schimbă proprietatea inCart în true:

function addToCart(id) { setProds(prods.map(prod => { if (prod.id === id) { prod.inCart = true; } return prod; })); }

În tag-ul cu produsul să adăugăm un atribut, în care transmitem funcția creată de noi, precum și un atribut, în care transmitem id-ul produsului:

const items = prods.map(prod => { return <Product key ={prod.id} id ={prod.id} name ={prod.name} cost ={prod.cost} inCart ={prod.inCart} addToCart={addToCart} />; });

După cum vedeți, în props-urile componentelor se pot transmite nu numai unele date, ci și funcții.

Codul final al clasei Products va fi următorul:

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>; }

Acum în clasa copil vom avea acces la funcția addToCart. Să apelăm această funcție la click pe buton, transmitându-i ca parametru id-ul produsului:

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>; }

Se va întâmpla ca la click pe butonul din componenta copil să fie apelată funcția părintelui, care va modifica starea părintelui. Modificarea stării părintelui va declanșa rerandarea și va redesena produsul nostru, transmitându-i prop-ul modificat.

Luați componenta User din lecția anterioară. Faceți astfel încât în ea să apară un buton pentru banarea utilizatorului.

runlkkkaen