在PHP(或傳統的web)裡,是透用Form以及http post,在submit後,送出Form裡的欄位內容給伺服器。在javascript裡,可以利用document.getElementById取得DOM的內容,再利用http post將資料送到伺服器。未來,在介紹FAST API(或Firebase)時,我們會介紹如何將資料送到伺服器。
在react裡,並不建議直接去取得DOM的內容,所以,寫法就跟javascript不一樣了。在react裡,則是在輸入時(onChange)就將內容放到state裡,並將value設為state。(詳參:Responding to Events)
我們在productList.tsx,新增一個元件包含兩個輸入框:
function ProductAdd(){
return (
<Box>
產品描述:<input type="text" name="desc" value={desc} onChange={handleClickDesc}/><br/>
產品價格:<input type="number" name="price" value={price} onChange={handleClickPrice}/><br/>
</Box>
)
}
在ProductList裡,加上ProductAdd。
<Container maxWidth="sm">
<Box>
<List subheader="Product list" aria-label="product list">
{products.map((product, index) =>
<ListItemButton
selected={selectedIndex === index}
onClick={(event) => handleListItemClick(event, index)}
divider key={product.desc}>
<ListItemText primary={product.desc} secondary={product.price}>
</ListItemText>
</ListItemButton>)}
</List>
</Box>
**<ProductAdd/>**
</Container>
e是onChange預設傳給被呼叫方法的第一個參數,可以改為任何的變數名稱。可以利用console.log(e.target),就可以看到是取得DOM的元件,再從e.target中取得value,將value放到state裡,注意,因為是onChange,所以,每進行一次內容更動 (輸入一個字)就會觸發call back function(如:handleClickDesc)。
<aside> ⚠️
注意,以下內容要放在ProductAdd哩,否則,當我們輸入內容時,會因為ProductList及ProductAdd一直被重新產生,而導致輸入時一直要重新點輸入框才能繼續輸入。
</aside>
const [desc, setDesc] = useState("");
const [price, setPrice] = useState(0);
<aside> 📢 因為price是數字,要記得利用Number()將輸入內容轉成數字。
</aside>
function handleClickDesc(e) {
setDesc(e.target.value);
}
function handleClickPrice(e) {
setPrice(Number(e.target.value));
}
因為我們使用typescript,所以要定義e的資料型態:
function handleClickDesc(e: React.ChangeEvent<HTMLInputElement>) {
setDesc(e.target.value);
}
function handleClickPrice(e: React.ChangeEvent<HTMLInputElement>) {
setPrice(Number(e.target.value));
}
利用useState(),管理desc及price。
<aside> 📢 如果不用useState(),在畫面上就看不到輸入的內容。因為輸入框的值綁訂了desc及price。
</aside>
接下來,加個按鈕,在點擊按鈕時,就可以呼叫update函數,將輸入內容加到產品清單陣列中。