1 2 3 4 5 6 7 8
| const [inputState, setInputState] = useState('casper');
return ( <div> <label htmlFor="username">使用者名稱 {inputState}</label> <input id="username" type="text" value={inputState} onChange={e => setInputState(e.target.value)}/> </div>)
|
使用 input 表單時,
- 將 useState 的資料綁定到 value
- 偵聽 onChange 事件,將值用 setInputState 寫入 state。
select 選單
1 2 3 4 5 6 7 8 9
| const optionsList = ['台北', '台中', '高雄']; const [selectState, setSelectState] = useState('');
<select name="" id="" onChange={ e => setSelectState(e.target.value) }> <option value="" disabled>-- 請選擇地區 --</option> { optionsList.map((city) => <option value={city} key={city}> { city } </option>) } </select>
|
使用 select 選單時:
- 定義 option 資料陣列
- 用 map 將 option 渲染到 select 內,並帶入 value
- 再 select 偵聽 onChange 事件,用 setSelectState 寫入資料
select 多選
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const optionsList = ['台北', '台中', '高雄']; const [selectState, setSelectState] = useState([]);
<select name="" value={selectState} id="" onChange={ e => { const options = [...e.target.selectedOptions].map(option => option.value); setSelectState(options); }} multiple={true}> <option value="" disabled>-- 請選擇地區 --</option> { optionsList.map((city) => <option value={city} key={city}> { city } </option>) } </select>
|
使用 select 多選時:
- useState 要以空陣列定義
- select 監聽 onChange 事件時,資料會放在
e.target.selectedOptions
,可用 map 將值取回
radio 單選題
1 2 3 4 5 6 7 8
| const [check, setCheck] = useState(false);
<label htmlFor="isCheck">確認狀態 {check.toString()}</label> <input id="isCheck" type="checkbox" onChange={e => { setCheck(e.target.checked); }} value={check}/>
|
radio 單選是用來了解用戶是否點擊,useState 預設可用 false。 用戶點擊後用 setCheck 將值寫入。
checkbox 複選
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const [checkList, setCheckList] = useState([]); const hendleCheckList = (e) => { if (e.target.checked) { setCheckList([...checkList, e.target.value]) } else { setCheckList(checkList.filter((item) => item !== e.target.value)) } }
<label htmlFor="checkList1">炒麵</label> <input id="checkList1" type="checkbox" name="like" onChange={hendleCheckList} value='炒麵' /> <label htmlFor="checkList2">鍋燒意麵</label> <input id="checkList2" type="checkbox" name="like" onChange={hendleCheckList} value='鍋燒意麵' /> <label htmlFor="checkList3">炸薯條</label> <input id="checkList3" type="checkbox" name="like" onChange={hendleCheckList} value='炸薯條' />
|
用 checkbox 複選時,一樣用陣列定義 state,onChange 偵聽的函式裡,要判斷此時用戶是勾選狀態嗎,是的話將 value 加入陣列,否的話則將 value 移除陣列。
表單送出
在 react 製作表單送出時:
- useState 設定要送出的表單物件
- 物件的屬性和 input 的 name 要一樣
- 每個 input 綁定 onChange 事件,用 hendleInputChange 來寫入 value 到物件
- 送出按鈕 type 為 submit, form 綁定 onSubmit 事件送出表單
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| const App = () => { const [formData, setFormData] = useState({ username: 'Casper', password: '123456', isCheck: false, });
const hendleInputChange = (e) => { const value = e.target.type === 'checkbox' ? e.target.checked : e.target.value; const name = e.target.name; setFormData({ ...formData, [name]: value, }) }
const handleSubmit = (e) => { e.preventDefault(); } return (<div> <form onSubmit={handleSubmit}> <div className="mb-3"> <label htmlFor="username" className="form-label">使用者名稱</label ><input id="username" type="text" className="form-control" name="username" onChange={hendleInputChange} value={formData.username}/> </div> <div className="mb-3"> <label htmlFor="password" className="form-label">密碼</label ><input id="password" type="password" className="form-control" name="password" onChange={hendleInputChange} value={formData.password} /> </div> <div className="mb-3"> <label htmlFor="isCheck">確認狀態</label> <input id="isCheck" type="checkbox" name="isCheck" onChange={hendleInputChange} value={formData.isCheck}/> </div> <button type="submit" className="btn btn-primary">送出</button> </form> </div>) }
|
常見表單監聽方法
1 2 3 4 5 6 7 8
| <form onSubmit={formHandleSubmit}> <div className="mb-3"> <label htmlFor="search2" className="form-label">搜尋</label> <input id="search2" type="search" className="form-control" name="search" onChange={(e) => setSearch(e.target.value)} value={search} /> </div> </form>
|
當 form 裡只有一個 input 時,按下 enter 能直接觸發表單送出,就算 input 的 type 不是 submit
1 2 3 4 5 6 7 8 9 10 11 12
| const enterHandlerSubmit = (e) => { if (e.key === 'Enter') { console.log('開始搜尋', search) } } <label htmlFor="search1" className="form-label">搜尋</label> {} <input id="search1" type="search" className="form-control" name="search" value={search} onChange={(e) => setSearch(e.target.value)} onKeyPress={enterHandlerSubmit}
|
一般表單監聽可用 onChange 及時寫入值,用 onKeyPress 來送出表單
檔案上傳
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const uploadFile = async (file) => { const formData = new FormData(); formData.append('file-to-upload', file); try { const res = await axios.post(`/v2/api/${apiPath}/admin/upload`, formData); console.log(res.data.imageUrl); } catch(error) { alertError(error.response.data.message); } }
<div> <p>或上傳檔案</p> <input type="file" onChange={e => uploadFile(e.target.files[0])} /> </div>
|
在 react 裡要用 input 上傳檔案時:
- input type 選擇 file
- 偵聽 onChange 事件
- 檔案會在 e.target.files[0] 裡面
- 用 new FormData 建立表單物件
- formData 帶入欄位和值
- 將建立的表單物件發送到 api