⊗jsrtPmCpEPS 88 of 112 menu

Editing Parent State in Child Component in React

Let's now edit our products using inputs. To do this, we'll make a button in the child component.

The first time you click this button, instead of the name and price with the product, let inputs for editing them appear, and the second time you click, let texts appear again instead of inputs.

Let's make a change to the array with products by adding the isEdit property (and remove the work with the basket for simplicity):

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 Component

Let's make an editing button in the product:

function Product({ id, name, cost, isEdit }) { return <div> name: <span>{name}</span> cost: <span>{cost}</span> <button>edit</button> </div>; }

Let's make it so that when this button is clicked, some function toggleMode passed from the parent component is called:

function Product({ id, name, cost, isEdit, toggleMode }) { return <div> name: <span>{name}</span> cost: <span>{cost}</span> <button onClick={() => toggleMode(id)}> edit </button> </div>; }

We don't have an implementation of toggleMode yet, but we know that it will be located in the parent component, take the id product as a parameter, and change the isEdit product property to the opposite.

Let's also make it so that the button text changes with each click:

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>; }

Let's now make it so that in edit mode we have inputs with data, and in normal mode - spans:

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>; }

Let's bind an event onChange to our inputs, in which we will call some parent function 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>; }

Component Products

Let's now move on to the Products component. Let's implement the toggleMode function in it:

function toggleMode(id) { setProds(prods.map(prod => { if (prod.id === id) { prod.isEdit = !prod.isEdit; } return prod; })); }

We also implement the function editProd in it:

function editProd(id, field, event) { setProds(prods.map(prod => { if (prod.id === id) { prod[field] = event.target.value; } return prod; })); }

We will pass our functions toggleMode and editProd to the tag with product attributes:

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} />; });

The final code for the Products component will be as follows:

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>; }

Practical tasks

Perform similar operations with the Users and User components you created in the previous lessons.

enru