Промена стања родитеља у дочерном компоненту у React
У претходном уроку стање са подацима је чувано у родитељском компоненту, а дочерне компоненте су примале те податке у виду пропса.
Рецимо сада да желимо да мењамо наше производе.
Направимо, на пример, дугме које ће
ставити наш производ у корпу. За почетак
хајде да додамо у наш низ са производима
поље 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 из претходног
урока. Направите тако да у њој се појави
дугме за банирање корисника.