Tėvinio komponento būsenos redagavimas vaikiniame komponente React

Dabar redaguokime savo produktus naudodami įvesties laukus. Tam vaikiniame komponente sukurkime mygtuką.

Paspaudus pirmą kartą šį mygtuką, vietoj pavadinimo ir kainos su produktu tegul atsiranda įvesties laukai jų redagavimui, o paspaudus antrą kartą vietoj įvesties laukų vėl atsiranda tekstai.

Atlikime pakeitimą produktų masyve, pridėdami savybę isEdit (o darbą su krepšeliu dėl paprastumo pašalinkime):

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

Komponentas Product

Produkte sukurkime redagavimo mygtuką:

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

Padarykime taip, kad paspaudus šį mygtuką būtų iškviesta kokia nors funkcija toggleMode, perduota iš tėvinio komponento:

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

Kol kas neturime toggleMode realizacijos, bet žinome, kad ji bus talpinama tėviniame komponente, parametru priims produkto id ir pakeis savybę isEdit produkto į priešingą.

Taip pat padarykime, kad mygtuko tekstas keistųsi kiekvienu paspaudimu:

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

Dabar padarykime taip, kad redagavimo režime mūsų turėtų būti įvesties laukai su duomenimis, o įprastame režime - span elementai:

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

Priskirkime mūsų įvesties laukams įvykį onChange, kuriame iškviessime kažkokią tėvinę funkciją editProd:

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

Komponentas Products

Dabar pereikime į komponentą Products. Jame realizuokime funkciją toggleMode:

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

Taip pat jame realizuokime funkciją editProd:

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

Į produkto tagą atributais perduokime mūsų funkcijas toggleMode ir editProd:

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

Galutinis komponento Products kodas gausis toks:

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

Praktinės užduotys

Задание 1

Atlikite analogiškus veiksmus su komponentais Users ir User, kuriuos sukūrėte ankstesnėse pamokose.