Mengubah State Komponen Induk dalam Komponen Anak di React
Dalam pelajaran sebelumnya, state yang mengandung data disimpan dalam komponen induk, manakala komponen anak menerima data tersebut dalam bentuk props.
Sekarang katakan kita ingin mengubah produk kita.
Mari kita buat, sebagai contoh, satu butang yang akan
meletakkan produk kita ke dalam troli. Sebagai permulaan
mari kita tambahkan medan inCart ke dalam array produk kita,
yang menunjukkan sama ada produk tersebut berada dalam troli atau tidak:
const initProds = [
{id: id(), name: 'product1', cost: 100, inCart: false},
{id: id(), name: 'product2', cost: 200, inCart: false},
{id: id(), name: 'product3', cost: 300, inCart: false},
];
Dalam komponen Products, tambahkan satu lagi atribut
inCart ke dalam tag produk:
function Products() {
const [prods, setProds] = useState(initProds);
const items = prods.map(prod => {
return <Product
key ={prod.id}
name ={prod.name}
cost ={prod.cost}
inCart={prod.inCart}
/>;
});
return <div>
{items}
</div>;
}
Mari dalam komponen anak Product
kita buat paparan maklumat tentang troli dan butang
untuk menambah ke troli:
function Product({ id, name, cost, inCart }) {
return <div>
name: <span>{name}</span>,
cost: <span>{cost}</span>,
<span>{inCart ? 'in cart' : 'not in cart'}</span>
<button>to cart</button>
</div>;
}
Melaksanakan Penambahan
Mengikut peraturan React, komponen tidak sepatutnya
mengubah propsnya sendiri. Ini bermakna
komponen anak tidak boleh meletakkan dirinya sendiri
ke dalam troli dengan mengubah prop inCart.
Ini adalah tidak betul.
Cara yang betul adalah dengan meminta komponen induk
untuk mengubah state prodsnya, dengan meletakkan
produk tertentu ke dalam troli.
Mari kita lihat bagaimana ia dilakukan.
Dalam komponen induk, buat fungsi addToCart,
yang menerima id produk sebagai parameter
dan untuk produk tersebut menukar sifat inCart
kepada true:
function addToCart(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.inCart = true;
}
return prod;
}));
}
Dalam tag produk, tambahkan atribut, di mana kita
menghantar fungsi yang kita buat, dan juga
atribut, di mana kita menghantar id produk:
const items = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name ={prod.name}
cost ={prod.cost}
inCart ={prod.inCart}
addToCart={addToCart}
/>;
});
Seperti yang anda lihat, dalam props komponen anda boleh menghantar bukan sahaja data, malah fungsi juga.
Kod akhir untuk kelas Products adalah
seperti berikut:
function Products() {
const [prods, setProds] = useState(initProds);
function addToCart(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.inCart = true;
}
return prod;
}));
}
const items = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name ={prod.name}
cost ={prod.cost}
inCart ={prod.inCart}
addToCart={addToCart}
/>;
});
return <div>
{items}
</div>;
}
Sekarang dalam kelas anak, kita akan mempunyai akses kepada
fungsi addToCart. Panggil fungsi ini
pada klik butang, dengan menghantar
id produk sebagai parameter:
function Product({ id, name, cost, inCart, addToCart }) {
return <div>
name: <span>{name}</span>,
cost: <span>{cost}</span>,
<span>{inCart ? 'in cart' : 'not in cart'}</span>
<button onClick={() => addToCart(id)}>to cart</button>
</div>;
}
Hasilnya, apabila butang dalam komponen anak diklik, fungsi induk akan dipanggil, yang akan mengubah state induk. Perubahan state induk akan menyebabkan penyemakan semua semula dan melukis semula produk kita, dengan menghantar prop yang diubah kepadanya.
Ambil komponen User dari pelajaran
sebelumnya. Buat supaya di dalamnya muncul
butang untuk menyekat pengguna.