Vecāku komponenta stāvokļa rediģēšana bērna komponentā React

Tagad rediģēsim mūsu produktus izmantojot ievades laukus. Lai to izdarītu, bērna komponentā izveidosim pogu.

Pirmajā nospiešanā uz šīs pogas, produkta nosaukuma un cenas vietā parādīsies ievades lauki to rediģēšanai, bet otrajā nospiešanā ievades lauku vietā atkal parādīsies teksti.

Ieviesīsim izmaiņas produktu masīvā, pievienojot īpašību isEdit (un groza darbību vienkāršības labad noņemsim):

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

Komponents Product

Izveidosim produktā pogu rediģēšanai:

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

Padarīsim tā, lai noklikšķinot uz šīs pogas tiktu izsaukta kāda funkcija toggleMode, kas nodota no vecāka komponenta:

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

Pašlaik mums nav toggleMode implementācijas, bet mēs zinām, ka tā atradīsies vecāka komponentā, parametrā pieņems produkta id un mainīs produkta īpašību isEdit uz pretējo.

Arī padarīsim tā, lai pogas teksts mainītos katru reizi nospiežot:

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

Tagad padarīsim tā, lai rediģēšanas režīmā mums būtu ievades lauki ar datiem, bet parastajā režīmā - span elementi:

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

Piesaistīsim mūsu ievades laukiem notikumu onChange, kurā izsauksim kādu vecāka funkciju 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>;
}

Komponents Products

Tagad pāriesim uz komponentu Products. Implementēsim tajā funkciju toggleMode:

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

Arī implementēsim tajā funkciju editProd:

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

Produkta tagā ar atribūtiem nodosim mūsu funkcijas toggleMode un 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}
  />;
});

Komponenta Products galīgais kods būs šāds:

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

Praktiskie uzdevumi

Задание 1

Veiciet līdzīgas darbības ar komponentiem Users un User, kurus jūs izveidojāt iepriekšējās nodarbībās.