Bewerken van parent state in een child component in React

Laten we nu onze producten gaan bewerken met behulp van inputs. Hiervoor maken we een knop in het child component.

Laat bij de eerste klik op deze knop in plaats van de naam en prijs van het product, inputs verschijnen om ze te bewerken, en bij de tweede klik weer teksten verschijnen in plaats van de inputs.

Laten we een wijziging aanbrengen in de array met producten, door een eigenschap isEdit toe te voegen (en voor de eenvoud verwijderen we het werk met de winkelwagen):

jsxconst 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},
];

Component Product

Laten we een knop maken in het product voor bewerken:

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

Laten we ervoor zorgen dat bij een klik op deze knop een bepaalde functie toggleMode wordt aangeroepen, die doorgegeven is vanuit het parent component:

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

We hebben nog geen implementatie van toggleMode, maar we weten dat deze zich zal bevinden in het parent component, een id parameter zal accepteren en de eigenschap isEdit van het product zal veranderen naar de tegenovergestelde waarde.

Laten we ook ervoor zorgen dat de tekst van de knop verandert bij elke klik:

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

Laten we nu ervoor zorgen dat in de bewerkmodus er inputs zijn met de gegevens, en in de normale modus - spans:

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

Laten we aan onze inputs de gebeurtenis onChange binden, waarin we een bepaalde parent functie editProd zullen aanroepen:

jsxfunction 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

Laten we nu naar het component Products gaan. Laten we daarin de functie toggleMode implementeren:

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

Laten we daarin ook de functie editProd implementeren:

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

Laten we in de tag van het product onze functies toggleMode en editProd als attributen doorgeven:

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

De uiteindelijke code van het component Products wordt als volgt:

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

Praktische taken

Задание 1

Voer vergelijkbare handelingen uit met de componenten Users en User, die je hebt gemaakt in eerdere lessen.