我正在处理包含2个字段的登录表单。电子邮件和密码。当我使用代表两个字段的2 useState时,然后当我使用handleChange更新状态时,两个状态都将更新。这不是故意的。
const [email, setEmail] = useState()
const [password, setPassword] = useState()
const handleChange = e => {
const {value} = e.target
setEmail(value)
setPassword(value)
}
我不想使用多个事件处理程序来处理每个输入字段。我尝试过
const [state , setState] = useState({
email : "",
password : ""
})
const handleChange = e => {
const {name , value} = e.target
setState({
[name] : value
})
}
但是这一次更新一个属性。并且其他财产价值迷失了。因此,有什么办法可以像使用状态组件一样,用一个事件处理程序更新所有输入字段。
this.state = {
email : "",
password : ""
}
const handleChange = e => {
const {name , value} = e.target
this.setState({
[name] : value
})
}
答案 0 :(得分:1)
您可以使用react提供的UseReducer。它非常简单,并且提供了非常干净的代码。
import React, {useReducer} from 'react';
const initialState = {
email: '',
password: ''
};
function reducer(state, action) {
switch (action.type) {
case 'email':
return {
...state,
email: action.payload
};
case 'password':
return {
...state,
password: action.payload
};
default:
throw new Error();
}
}
const Login = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const handleChange = event => dispatch({ type: event.target.name, payload: event.target.value.trim() });
return (
<div className="container">
<div className="form-group">
<input
type="email"
name="email"
value={state.email}
onChange={handleChange}
placeholder="Enter Email"
/>
</div>
<div className="form-group">
<input
type="password"
name="password"
value={state.password}
onChange={handleChange}
placeholder="Enter Password"
/>
</div>
<div className="form-group">
<button className="btn btn-info">Login</button>
</div>
</div>
)
}
export default Login;
答案 1 :(得分:1)
您可以使用prevState。
const [state, setState] = useState({ fruit: "", price: "" });
const handleChange = e => {
const { name, value } = e.target;
setState(prevState => ({
...prevState,
[name]: value
}));
};
<input
value={state.fruit}
type="text"
onChange={handleChange}
name="fruit"
/>
<input
value={state.price}
type="text"
onChange={handleChange}
name="price"
/>
答案 2 :(得分:0)
您应将setState与回调函数一起使用:
setState(prev => ({
...prev,
email: 'new mail',
}))
您将创建一个新的状态对象,该对象由先前的状态创建。而且您可以覆盖所需的任何内容。 如果您有一个复杂的状态对象,则需要更多的新对象。
答案 3 :(得分:0)
尝试
this.state = { 电子邮件:“”, 密码:“” }
const handleChange = e => {
const updated = {name , value} = e.target
const next = {...this.state, ...updated}
this.setState({next})
}
答案 4 :(得分:0)
您可以像这样创建自定义钩子:
import React, { useState } from 'react';
export default function App() {
const username = useFormInput(''); // use it here
const password = useFormInput(''); // & here...
return (
<div>
<form>
<input type='text' placeholder='username' {...username} />
<input type='password' placeholder='password' {...password} />
<input type='submit' />
</form>
</div>
);
}
// custom hook
function useFormInput (initialValue) {
const [value, setValue] = useState(initialValue);
const handleChange = event => {
setValue(event.target.value);
};
return { value, onChange: handleChange };
};
答案 5 :(得分:0)
感谢DoğancanArabacı。我试图模仿基于类的组件的state和setState,所以感觉不会改变。我的解决方案如下所示。
const [state , setState] = useState({
email : "",
password : ""
})
const handleChange = e => {
const {name , value} = e.target
setState( prevState => {
...prevState,
[name] : value
})
}
答案 6 :(得分:0)
// The useState Hook is used in React,
const {obj, setObj} = useState({ // Initially a value of `{}` object type
foo: {},
bar: {}
})
const handle = event => {
setObj({ // here `{}` is a new value of type object
...obj, // So, first use the ... operator to get the prevState
bar: { qux: {} } // then, update
})
}
答案 7 :(得分:0)
尝试一下:
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const handleChange = (name, e) => {
switch (name) {
case 'email':
setEmail(e);
break;
case 'password':
setPassword(e);
break;
default:
break;
}
};
您的输入:
<input
type="text"
onChange={ e => handleChange('email',e)}
name="email"
/>
<input
type="text"
onChange={ e => handleChange('password',e)}
name="password"
/>
答案 8 :(得分:0)
创建所有输入的字典
您可以使用输入的state
保存对象(用作字典)中每个输入的setState
和name
的引用。
以下示例也适用于checkbox
输入:
import React, { useState } from "react";
const setStateOfInput = 1;
function Form() {
const inputs = {}; // Dictionary used to save a reference [state, setState] for each input (e.g. inputs.todo)
const [todoInput, setTodoInput] = inputs.todo = useState("");
const [doneInput, setDoneInput] = inputs.done = useState(false);
function handleInput(e) {
let { name, value, type } = e.target;
// If input is a checkbox
if (type === "checkbox") value = e.target.checked;
inputs[name][setStateOfInput](value);
}
return (
<div>
<form>
<label>To Do</label>
<input name="todo" value={todoInput} onChange={handleInput} />
<label>Done</label>
<input name="done" type="checkbox" checked={doneInput} onChange={handleInput}/>
<button type="button">Add</button>
</form>
</div>
);
}
export default Form;
创建自定义钩子
此外,可以重构以上内容以创建一个自定义钩子,该钩子可用于其他组件中的表单/输入:
function useInputState(initialValue, name, inputsDict) {
if (inputsDict[name]) throw new Error(`input "${name}" already exists.`);
inputsDict[name] = useState(initialValue);
return inputsDict[name]
}
|
const inputs = {}; // Dictionary used by `useInputState`
const [todoInput, setTodoInput] = useInputState("", "todo", inputs);