Режими на работа чрез състояния на наследници компоненти в React
Нека нашият масив с продукти сега изглежда по следния начин:
const initProds = [
{id: id(), name: 'prod1', cost: 'cost1', catg: 'catg1'},
{id: id(), name: 'prod2', cost: 'cost2', catg: 'catg2'},
{id: id(), name: 'prod3', cost: 'cost3', catg: 'catg3'},
];
Нека да изведем тези продукти под формата на HTML
таблица. В същото време ще направим така, че при натискане
върху която и да е клетка от таблицата в тази клетка да се появи
поле за въвеждане за редактиране. За решаване на задачата
ще направим 3 компонента.
Компонентът Products ще съхранява състоянието
с продукти и ще използва компоненти Product
за извеждане на продукти. Компонентът Product
от своя страна също ще използва компоненти
ProductField за извеждане на определено
поле на продукта (име, цена, категория).
Компонентът ProductField ще показва или
текста на полето, или поле за въвеждане за неговото
редактиране. В този случай режимът на редактиране
или показване нека се регулира от състоянието
на този компонент.
Тоест няма да съхраняваме режима в родителското състояние. Там би било много неудобно, тъй като ще трябва да посочим режим за всяко поле на продукта, което би превърнало нашето състояние в нещо подобно:
const initProds = [
[
{field: 'name', value: 'prod1', isEdit: false},
{field: 'cost', value: 'cost1', isEdit: false},
{field: 'catg', value: 'catg1', isEdit: false},
],
[
{field: 'name', value: 'prod2', isEdit: false},
{field: 'cost', value: 'cost2', isEdit: false},
{field: 'catg', value: 'catg2', isEdit: false},
],
[
{field: 'name', value: 'prod3', isEdit: false},
{field: 'cost', value: 'cost3', isEdit: false},
{field: 'catg', value: 'catg3', isEdit: false},
],
]
Ние обаче няма да направим такова състояние,
а ще оставим това, което беше. Просто всеки
екземпляр на компонента ProductField
чрез собственото си състояние ще регулира
режима: или редактиране, или показване.
По този начин ще се получи, че родителският компонент ще съхранява състоянието с данните, а нашият внук компонент ще получава тези данни чрез пропсове и в същото време ще има собствено състояние за промяна на своя режим.
И така, нека реализираме описаното.
Компонент Products
function Products() {
const [prods, setProds] = useState(initProds);
function changeField(id, field, event) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod[field] = event.target.value;
}
return prod;
}));
}
const rows = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name={prod.name}
cost={prod.cost}
catg={prod.catg}
changeField={changeField}
/>;
});
return <div>
<table>
<tbody>
{rows}
</tbody>
</table>
</div>;
}
Компонент Product
function Product({ id, name, cost, catg, changeField }) {
return <tr>
<ProductField id={id} text={name} type="name" changeField={changeField} />
<ProductField id={id} text={cost} type="cost" changeField={changeField} />
<ProductField id={id} text={catg} type="catg" changeField={changeField} />
</tr>;
}
Компонент ProductField
function ProductField({ id, text, type, changeField }) {
const [isEdit, setIsEdit] = useState(false);
return <td>
{
isEdit
? <input
value={text}
onChange={event => changeField(id, type, event)}
onBlur={() => setIsEdit(false)}
/>
: <span onClick={() => setIsEdit(true)}>{text}</span>
}
</td>;
}
Практически задачи
Изпълнете подобни операции с компонентите
Users и User, създадени от вас
в предишни уроци.