Edición del estado del padre en un componente hijo en React
Ahora vamos a editar nuestros productos usando inputs. Para ello, en el componente hijo hagamos un botón.
Al primer clic en este botón, que en lugar del nombre y precio del producto aparezcan inputs para su edición, y al segundo clic en lugar de los inputs aparezcan nuevamente los textos.
Hagamos un cambio en el array de productos, agregando
la propiedad isEdit (y eliminaremos el trabajo con el carrito
por simplicidad):
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},
];
Componente Product
Hagamos en el producto un botón para editar:
function Product({ id, name, cost, isEdit }) {
return <div>
nombre: <span>{name}</span>
precio: <span>{cost}</span>
<button>editar</button>
</div>;
}
Hagamos que al hacer clic en este botón
se llame a alguna función toggleMode,
pasada desde el componente padre:
function Product({ id, name, cost, isEdit, toggleMode }) {
return <div>
nombre: <span>{name}</span>
precio: <span>{cost}</span>
<button onClick={() => toggleMode(id)}>
editar
</button>
</div>;
}
Aún no tenemos la implementación de toggleMode,
pero sabemos que estará ubicada
en el componente padre, recibirá como parámetro
el id del producto y cambiará la propiedad isEdit
del producto al valor opuesto.
Hagamos también que el texto del botón cambie en cada clic:
function Product({ id, name, cost, isEdit, toggleMode }) {
return <div>
nombre: <span>{name}</span>
precio: <span>{cost}</span>
<button onClick={() => toggleMode(id)}>
{isEdit ? 'guardar': 'editar'}
</button>
</div>;
}
Ahora hagamos que en el modo de edición tengamos inputs con los datos, y en el modo normal - spans:
function Product({ id, name, cost, isEdit, toggleMode }) {
return <div>
nombre: {isEdit ? <input value={name} /> : <span>{name}</span>}
precio: {isEdit ? <input value={cost} /> : <span>{cost}</span>}
<button onClick={() => toggleMode(id)}>
{isEdit ? 'guardar': 'editar'}
</button>
</div>;
}
Asociemos a nuestros inputs el evento onChange,
en el cual llamaremos a alguna función parental
editProd:
function Product({ id, name, cost, isEdit, toggleMode, editProd }) {
return <div>
nombre: {
isEdit
? <input value={name} onChange={event => editProd(id, 'name', event)} />
: <span>{ name }</span>
}
precio: {
isEdit
? <input value={cost} onChange={event => editProd(id, 'cost', event)} />
: <span>{ cost }</span>
}
<button onClick={() => toggleMode(id)}>
{isEdit ? 'guardar': 'editar'}
</button>
</div>;
}
Componente Products
Ahora pasemos al componente Products.
Implementemos en él la función toggleMode:
function toggleMode(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.isEdit = !prod.isEdit;
}
return prod;
}));
}
También implementemos en él la función editProd:
function editProd(id, field, event) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod[field] = event.target.value;
}
return prod;
}));
}
En la etiqueta del producto pasemos como atributos nuestras
funciones toggleMode y 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}
/>;
});
El código final del componente Products
será el siguiente:
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>;
}
Tareas prácticas
Realiza operaciones similares con los componentes
Users y User, creados por ti
en lecciones anteriores.