React Hooks 与表单应用
目录
1. input
文本输入框
const App = () => {
const [form, setForm] = useState({
age: null,
email: "",
})
const handleChange = event => {
const { name, value } = event.target
setForm(prevState => ({
...prevState,
[name]: value,
}))
}
return (
<form>
<label>
Age
<input
type="number"
name="age"
value={form.age}
onChange={handleChange}
/>
</label>
<label>
Email
<input
type="email"
name="email"
value={form.email}
onChange={handleChange}
/>
</label>
</form>
)
}
2. radio
单选按钮
const CATEGORY_OPTIONS = ["Anime", "Book", "Game", "Real", "Music"]
const App = () => {
const [form, setForm] = useState({
category: "",
})
const handleChange = event => {
const { name, value } = event.target
setForm(prevState => ({
...prevState,
[name]: value,
}))
}
const categoryOptions = CATEGORY_OPTIONS.map(elem => (
<>
<input
type="radio"
name="category"
value={elem}
checked={form.category === elem}
onChange={handleChange}
/>
{elem}
<br />
</>
))
return (
<>
{categoryOptions}
<button onClick={() => console.log(form)}>提交</button>
</>
)
}
3. select
下拉列表
const SOURCE_OPTIONS = [
{ key: "bilibili", name: "哔哩哔哩" },
{ key: "acfun", name: "AcFun" },
{ key: "youtube", name: "Youtube" },
{ key: "netflix", name: "Netflix" },
]
const App = () => {
const [form, setForm] = useState({
source: "bilibili",
})
const handleChange = event => {
const { name, value } = event.target
setForm(prevState => ({
...prevState,
[name]: value,
}))
}
const sourceOptions = SOURCE_OPTIONS.map(elem => (
<option value={elem.key}>{elem.name}</option>
))
return (
<>
<select name="source" value={form.source} onChange={handleChange}>
{sourceOptions}
</select>
<button onClick={() => console.log(form)}>提交</button>
</>
)
}
4. checkbox
复选框
4.1 Array 下标更新checked
const SOURCE_OPTIONS = [
{ key: "bilibili", name: "哔哩哔哩" },
{ key: "acfun", name: "AcFun" },
{ key: "youtube", name: "Youtube" },
{ key: "netflix", name: "Netflix" },
]
const App = () => {
const [source, setSource] = useState(
SOURCE_OPTIONS.map(elem => ({
...elem,
checked: false, // 初始化为全不选
}))
)
const handleChange = indexToUpdate => {
// copy原state 然后更新当前下标
const updatedState = [...source]
updatedState[indexToUpdate].checked = !updatedState[indexToUpdate].checked
setSource(updatedState)
}
const sourceOptions = source.map((elem, index) => (
<label key={elem.key}>
<input
type="checkbox"
name={elem.key}
onChange={() => handleChange(index)}
checked={source[index].checked}
/>
{elem.name}
<br />
</label>
))
return (
<>
{sourceOptions}
<button onClick={() => console.log(source)}>提交</button>
</>
)
}
4.2 利用 Object 更新
Object
则可以直接对指定的key
更新, 就不用下标了. 但如果给的数据是 array of objects, 则需要先转化成 Object.
同时更新 state 时也可以直接对每一层 copy.
setSource(prevState => ({
...prevState,
[name]: {
...prevState[name],
checked: checked,
},
}))
const SOURCE_OPTIONS = [
{ key: "bilibili", name: "哔哩哔哩" },
{ key: "acfun", name: "AcFun" },
{ key: "youtube", name: "Youtube" },
{ key: "netflix", name: "Netflix" },
]
const App = () => {
// 转化成Object 且每个元素初始化checked为不选
const initSource = SOURCE_OPTIONS.reduce(
(acc, elem) => ({ ...acc, [elem.key]: { ...elem, checked: false } }),
{}
)
const [source, setSource] = useState(initSource)
const handleChange = event => {
const { name, checked } = event.target
const updatedState = { ...source }
updatedState[name].checked = checked
setSource(updatedState)
}
const sourceOptions = Object.keys(source).map(elem => (
<label key={elem}>
<input
type="checkbox"
name={elem}
onChange={handleChange}
checked={source[elem].checked}
/>
{source[elem].name}
<br />
</label>
))
return (
<>
{sourceOptions}
<button onClick={() => console.log(source)}>提交</button>
</>
)
}