Modos de operação através de estados em componentes filhos no React
Suponha que nossa matriz de produtos agora tenha a seguinte aparência:
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'},
];
Vamos exibir esses produtos em uma tabela HTML.
Ao mesmo tempo, faremos com que, ao clicar em
qualquer célula da tabela, um campo de entrada
apareça nessa célula para edição. Para resolver
a tarefa, criaremos 3 componentes.
O componente Products armazenará o estado
com os produtos e usará os componentes Product
para exibir os produtos. O componente Product,
por sua vez, também usará os componentes
ProductField para exibir um determinado
campo do produto (nome, preço, categoria).
O componente ProductField mostrará
ou o texto do campo, ou um campo de entrada para sua
edição. E o modo de edição
ou exibição será regulado pelo estado
deste componente.
Ou seja, não armazenaremos o modo no estado do componente pai. Lá seria muito inconveniente, pois teríamos que especificar o modo para cada campo do produto, o que transformaria nosso estado em algo assim:
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},
],
]
No entanto, não faremos esse estado,
e manteremos aquele que tínhamos. Simplesmente, cada
instância do componente ProductField
usará seu próprio estado para regular
o modo: edição ou exibição.
Dessa forma, o componente pai armazenará o estado com os dados, e nosso componente neto receberá esses dados através de props e, ao mesmo tempo, terá seu próprio estado para alterar seu modo.
Então, vamos implementar o descrito.
Componente 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>;
}
Componente 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>;
}
Componente 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>;
}
Tarefas práticas
Realize operações semelhantes com os componentes
Users e User, criados por você
nas lições anteriores.