React 输入警告:组件正在将文本类型的受控输入更改为不受控制
React Input Warning: A component is changing a controlled input of type text to be uncontrolled
我正在使用一个 Fake API site. For front-end, I am using React typescript and React router dom for routing. I successfully login the email and password by using Fake API's login and redirect to list users, where I fetched the data from Fake API and shows the user's name, image. I used the edit button, after clicking the button it will redirect to my Update components where it will populate the input field then I will update the data. My update components work fine as expected but in my console, I am getting a warning as soon as I type my input field.Here is the Error visualization
练习 REST API
这是 React 更新组件
import React, { useState, useEffect } from "react";
import axios from "axios";
const Update = props => {
const [state, setState] = useState({
first_name: "",
last_name: "",
email: ""
});
const [loading, setLoading] = useState(false);
useEffect(() => {
axios
.get("https://reqres.in/api/users/" + props.match.params.id)
.then(response => {
setState({
first_name: response.data.data.first_name,
last_name: response.data.data.last_name,
email: response.data.data.email
});
})
.catch(function(error) {
console.log(error);
});
}, [props.match.params.id]);
const onChangeFirstName = e => {
setState({
first_name: e.target.value
});
};
const onChangeLastName = e => {
setState({
last_name: e.target.value
});
};
const onChangeEmail = e => {
setState({
email: e.target.value
});
};
const onSubmit = e => {
e.preventDefault();
setLoading(true);
const obj = {
first_name: state.first_name,
last_name: state.last_name,
email: state.email
};
axios
.patch("https://reqres.in/api/users/" + props.match.params.id, obj)
.then(res => console.log(res.data));
setLoading(false);
props.history.push("/users");
};
return (
<div>
<form onSubmit={onSubmit}>
<div className="form-group">
<label>First Name: </label>
<input
type="text"
className="form-control"
value={state.first_name}
onChange={onChangeFirstName}
id="first_name"
/>
</div>
<div className="form-group">
<label>Last Name: </label>
<input
type="text"
className="form-control"
value={state.last_name}
onChange={onChangeLastName}
id="last_name"
/>
</div>
<div className="form-group">
<label>Email: </label>
<input
type="email"
className="form-control"
value={state.email}
onChange={onChangeEmail}
id="email"
/>
</div>
<div className="form-group">
<button
className="btn waves-effect blue lighten-1"
type="submit"
name="action"
disabled={loading}
>
{loading ? "loading..." : "save"}
</button>
</div>
</form>
</div>
);
};
export default Update;
有了钩子,当你set the state
一个对象时,你需要自己合并所有的属性。换句话说,如果您使用 state updater
更新对象的 属性,则对象的其余属性不会自行合并,这与 class 组件中的 this.setState
不同。
将您的 onChange
修改为这样:
const onChangeFirstName = e => {
const val = e.target.value;
setState(prevState => ({
...prevState,
first_name: val
}));
};
还有快速建议:
您可以简化并只使用一个,而不是编写多个 onChange
。
像这样:
<input
type="text"
className="form-control"
value={state.first_name}
onChange={onChange}
id="first_name"
name="first_name" />
...
const onChange = e => {
const {name, value} = e.target;
setState(prevState => ({
...prevState,
[name]: value
}));
};
我正在使用一个 Fake API site. For front-end, I am using React typescript and React router dom for routing. I successfully login the email and password by using Fake API's login and redirect to list users, where I fetched the data from Fake API and shows the user's name, image. I used the edit button, after clicking the button it will redirect to my Update components where it will populate the input field then I will update the data. My update components work fine as expected but in my console, I am getting a warning as soon as I type my input field.Here is the Error visualization
练习 REST API这是 React 更新组件
import React, { useState, useEffect } from "react";
import axios from "axios";
const Update = props => {
const [state, setState] = useState({
first_name: "",
last_name: "",
email: ""
});
const [loading, setLoading] = useState(false);
useEffect(() => {
axios
.get("https://reqres.in/api/users/" + props.match.params.id)
.then(response => {
setState({
first_name: response.data.data.first_name,
last_name: response.data.data.last_name,
email: response.data.data.email
});
})
.catch(function(error) {
console.log(error);
});
}, [props.match.params.id]);
const onChangeFirstName = e => {
setState({
first_name: e.target.value
});
};
const onChangeLastName = e => {
setState({
last_name: e.target.value
});
};
const onChangeEmail = e => {
setState({
email: e.target.value
});
};
const onSubmit = e => {
e.preventDefault();
setLoading(true);
const obj = {
first_name: state.first_name,
last_name: state.last_name,
email: state.email
};
axios
.patch("https://reqres.in/api/users/" + props.match.params.id, obj)
.then(res => console.log(res.data));
setLoading(false);
props.history.push("/users");
};
return (
<div>
<form onSubmit={onSubmit}>
<div className="form-group">
<label>First Name: </label>
<input
type="text"
className="form-control"
value={state.first_name}
onChange={onChangeFirstName}
id="first_name"
/>
</div>
<div className="form-group">
<label>Last Name: </label>
<input
type="text"
className="form-control"
value={state.last_name}
onChange={onChangeLastName}
id="last_name"
/>
</div>
<div className="form-group">
<label>Email: </label>
<input
type="email"
className="form-control"
value={state.email}
onChange={onChangeEmail}
id="email"
/>
</div>
<div className="form-group">
<button
className="btn waves-effect blue lighten-1"
type="submit"
name="action"
disabled={loading}
>
{loading ? "loading..." : "save"}
</button>
</div>
</form>
</div>
);
};
export default Update;
有了钩子,当你set the state
一个对象时,你需要自己合并所有的属性。换句话说,如果您使用 state updater
更新对象的 属性,则对象的其余属性不会自行合并,这与 class 组件中的 this.setState
不同。
将您的 onChange
修改为这样:
const onChangeFirstName = e => {
const val = e.target.value;
setState(prevState => ({
...prevState,
first_name: val
}));
};
还有快速建议:
您可以简化并只使用一个,而不是编写多个 onChange
。
像这样:
<input
type="text"
className="form-control"
value={state.first_name}
onChange={onChange}
id="first_name"
name="first_name" />
...
const onChange = e => {
const {name, value} = e.target;
setState(prevState => ({
...prevState,
[name]: value
}));
};