Промена на состојбата на родителот во детски компонент во React
Во претходната лекција, состојбата со податоци се чуваше во родителскиот компонент, а детските компоненти ги добиваа тие податоци во форма на пропси.
Сега да речеме дека сакаме да ги менуваме нашите производи.
Да направиме, на пример, копче што ќе
го става нашиот производ во кошничката. За почеток
ајде да додадеме во нашиот производен array
поле inCart, кое покажува дали производот
е во кошничка или не:
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},
];
Во компонентот Products во тагот со производот
додадеме уште еден атрибут 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>;
}
Ајде во детскиот компонент Product
да направиме приказ на информации за кошничката и копче
за додавање во кошничката:
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>;
}
Го имплементираме додавањето
Според правилата на React компонентата не треба
да ги менува своите пропси. Ова значи дека
детската компонента не може сама да се
стави во кошничката, менувајќи го пропсот inCart.
Ова не е точно.
Правилно ќе биде да се побара од родителската компонента
да ја смени својата состојба prods, ставајќи
одреден производ во кошничката.
Ајде да погледнеме како се прави ова.
Во компонентата-родител да направиме функција addToCart,
која како параметар прима id на производот
и за тој производ го менува својството inCart
на true:
function addToCart(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.inCart = true;
}
return prod;
}));
}
Во тагот со производот да додадеме атрибут, во кој
ќе ја пренесеме креираната од нас функција, како и
атрибут, во кој ќе го пренесеме id на производот:
const items = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name ={prod.name}
cost ={prod.cost}
inCart ={prod.inCart}
addToCart={addToCart}
/>;
});
Како што гледате, во пропсите на компонентите може да се пренесуваат не само некои податоци, туку и функции.
Крајниот код на класата Products ќе излезе
следниов:
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>;
}
Сега во детската класа ќе ни биде достапна
функцијата addToCart. Да ја повикаме оваа функција
при клик на копчето, пренесувајќи и како параметар
id на производот:
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>;
}
Ќе испадне дека при клик на копчето во потомокот ќе се повика функцијата на родителот, која ќе ја промени родителската состојба. Промената на родителската состојба ќе предизвика пререндерирање и ќе го прецрта нашиот производ, пренесувајќи му го променетиот пропс.
Земете ја компонентата User од претходната
лекција. Направете така што во неа ќе се појави
копче за банирање на корисникот.