Редактиране на състоянието на родителя в детски компонент в React
Нека сега да редактираме нашите продукти с помощта на входни полета. За целта в детския компонент ще създадем бутон.
При първо натискане на този бутон нека вместо име и цена на продукта се появят входни полета за тяхното редактиране, а при второ натискане вместо входни полета отново да се появят текстове.
Ще направим промяна в масива с продукти, като добавим
свойство isEdit (а работата с кошницата
за простота ще премахнем):
const initProds = [
{id: id(), name: 'product1', cost: 100, isEdit: false},
{id: id(), name: 'product2', cost: 200, isEdit: false},
{id: id(), name: 'product3', cost: 300, isEdit: false},
];
Компонент Product
Нека направим бутон за редактиране в продукта:
function Product({ id, name, cost, isEdit }) {
return <div>
name: <span>{name}</span>
cost: <span>{cost}</span>
<button>edit</button>
</div>;
}
Нека направим така, че при кликване на този бутон
да се извика някаква функция toggleMode,
предадена от родителския компонент:
function Product({ id, name, cost, isEdit, toggleMode }) {
return <div>
name: <span>{name}</span>
cost: <span>{cost}</span>
<button onClick={() => toggleMode(id)}>
edit
</button>
</div>;
}
Засега нямаме реализация на toggleMode,
но знаем, че тя ще се намира
в родителския компонент, ще приема параметър
id на продукта и ще променя свойството isEdit
на продукта на противоположното.
Нека също така направим така, че текстът на бутона да се променя при всяко натискане:
function Product({ id, name, cost, isEdit, toggleMode }) {
return <div>
name: <span>{name}</span>
cost: <span>{cost}</span>
<button onClick={() => toggleMode(id)}>
{isEdit ? 'save': 'edit'}
</button>
</div>;
}
Сега нека направим така, че в режим на редактиране да имаме входни полета с данни, а в нормален режим - елементи span:
function Product({ id, name, cost, isEdit, toggleMode }) {
return <div>
name: {isEdit ? <input value={name} /> : <span>{name}</span>}
cost: {isEdit ? <input value={cost} /> : <span>{cost}</span>}
<button onClick={() => toggleMode(id)}>
{isEdit ? 'save': 'edit'}
</button>
</div>;
}
Нека свържем към нашите входни полета събитие onChange,
в което ще извикваме някаква родителска
функция editProd:
function Product({ id, name, cost, isEdit, toggleMode, editProd }) {
return <div>
name: {
isEdit
? <input value={name} onChange={event => editProd(id, 'name', event)} />
: <span>{ name }</span>
}
cost: {
isEdit
? <input value={cost} onChange={event => editProd(id, 'cost', event)} />
: <span>{ cost }</span>
}
<button onClick={() => toggleMode(id)}>
{isEdit ? 'save': 'edit'}
</button>
</div>;
}
Компонент Products
Нека сега да преминем към компонента Products.
Ще реализираме в него функцията toggleMode:
function toggleMode(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.isEdit = !prod.isEdit;
}
return prod;
}));
}
Също така ще реализираме в него функцията editProd:
function editProd(id, field, event) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod[field] = event.target.value;
}
return prod;
}));
}
В елемента с продукта ще предадем нашите
функции toggleMode и editProd като атрибути:
const items = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name={prod.name}
cost={prod.cost}
isEdit={prod.isEdit}
toggleMode={toggleMode}
editProd={editProd}
/>;
});
Крайният код на компонента Products
ще бъде следния:
function Products() {
const [prods, setProds] = useState(initProds);
function toggleMode(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.isEdit = !prod.isEdit;
}
return prod;
}));
}
function editProd(id, field, event) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod[field] = event.target.value;
}
return prod;
}));
}
const result = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name={prod.name}
cost={prod.cost}
isEdit={prod.isEdit}
toggleMode={toggleMode}
editProd={editProd}
/>;
});
return <div>
{result}
</div>;
}
Практически задачи
Изпълнете подобни операции с компонентите
Users и User, създадени от вас
в предишни уроци.