Tilatietojen käsittely Reactin lapsikomponenteissa
Oletetaan, että tuotetaulukkomme näyttää nyt seuraavalta:
const initProds = [
{id: id(), name: 'prod1', cost: 'cost1', catg: 'catg1'},
{id: id(), name: 'prod2', cost: 'cost2', catg: 'catg2'},
{id: id(), name: 'prod3', cost: 'cost3', catg: 'catg3'},
];
Esitetään nämä tuotteet HTML-taulukkona.
Tehdään myös niin, että minkä tahansa taulukon
solun klikkaaminen näyttää syötekentän muokkausta
varten. Ratkaistaksemme tehtävän luomme 3 komponenttia.
Komponentti Products säilyttää tilan
tuotteilla ja käyttää Product komponentteja
tuotteiden näyttämiseen. Komponentti Product
puolestaan käyttää ProductField komponentteja
näyttämään tietyn tuotteen kentän (nimi, hinta, kategoria).
Komponentti ProductField näyttää joko
kentän tekstin tai syötekentän sen muokkaamista
varten. Olkoon myös muokkaustila tai näyttötila
säädeltynä tämän komponentin tilan avulla.
Eli emme tallenna tilaa ylemmässä tasossa. Siellä se olisi erittäin hankalaa, koska meidän pitäisi määrittää tila jokaiselle tuotteen kentälle, mikä muuttaisi tilamme joksikin tällaiseksi:
const initProds = [
[
{field: 'name', value: 'prod1', isEdit: false},
{field: 'cost', value: 'cost1', isEdit: false},
{field: 'catg', value: 'catg1', isEdit: false},
],
[
{field: 'name', value: 'prod2', isEdit: false},
{field: 'cost', value: 'cost2', isEdit: false},
{field: 'catg', value: 'catg2', isEdit: false},
],
[
{field: 'name', value: 'prod3', isEdit: false},
{field: 'cost', value: 'cost3', isEdit: false},
{field: 'catg', value: 'catg3', isEdit: false},
],
]
Emme kuitenkaan tee sellaista tilaa,
vaan jätämme sen, joka oli. Yksinkertaisesti jokainen
ProductField komponentin ilmentymä
omassa tilassaan säätelee tilaa: joko muokkaus tai näyttö.
Siten käy niin, että ylemmän tason komponentti säilyttää tilan tiedoilla, ja meidän lapsenlapsikomponenttimme saa nämä tiedot propsien kautta ja sillä on samalla oma tilansa oman tilansa muuttamiseksi.
Joten, toteutetaan kuvattu.
Products-komponentti
function Products() {
const [prods, setProds] = useState(initProds);
function changeField(id, field, event) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod[field] = event.target.value;
}
return prod;
}));
}
const rows = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name={prod.name}
cost={prod.cost}
catg={prod.catg}
changeField={changeField}
/>;
});
return <div>
<table>
<tbody>
{rows}
</tbody>
</table>
</div>;
}
Product-komponentti
function Product({ id, name, cost, catg, changeField }) {
return <tr>
<ProductField id={id} text={name} type="name" changeField={changeField} />
<ProductField id={id} text={cost} type="cost" changeField={changeField} />
<ProductField id={id} text={catg} type="catg" changeField={changeField} />
</tr>;
}
ProductField-komponentti
function ProductField({ id, text, type, changeField }) {
const [isEdit, setIsEdit] = useState(false);
return <td>
{
isEdit
? <input
value={text}
onChange={event => changeField(id, type, event)}
onBlur={() => setIsEdit(false)}
/>
: <span onClick={() => setIsEdit(true)}>{text}</span>
}
</td>;
}
Käytännön tehtävät
Suorita samanlaiset toimenpiteet Users ja User
komponenttien kanssa, jotka loit
aiemmissa oppitunneissa.