我是新手,我对handleChange函数有问题。
我的程序加载带有json占位符数据的用户列表,并具有"编辑"按钮,单击此按钮会出现一个包含所选用户数据的表单。
问题:当我尝试编辑某些字段时,表单为"刷新"。
//User.js (contains the function)
import React from 'react';
import UserEdit from './components/UserEdit';
import UsersList from './components/UsersList'
import './App.css';
class Users extends React.Component {
constructor(){
super();
this.state = {
users: [],
displayList: 'block',
displayForm: 'none',
edit: false,
userEdit: {
id: null,
name: "",
email: "",
address: {
street: "",
suite: "",
city: "",
zipcode: ""
},
phone: ""
}
}
this.handleClick = this.handleClick.bind(this);
this.handleChange = this.handleChange.bind(this);
}
componentDidMount(){
this.getUsersList();
}
getUsersList(){
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => response.json())
.then(json => this.setState({users: json}));
}
getUserEdit(){
const url = 'https://jsonplaceholder.typicode.com/users/' + this.state.UserEdit.id;
fetch(url)
.then(response => response.json())
.then(json => this.setState({userEdit: json}));
}
handleClick(id){
if (this.state.displayList === 'block') {
this.setState({UserEdit: {id: id}});
this.setState({displayList: 'none', displayForm: 'block'})
this.setState({edit: true})
}
else {
this.setState({displayList: 'block', displayForm: 'none'})
this.setState({edit: false})
}
}
handleChange(event){
this.setState({
...this.state,
[event.target.value]: event.target.value
}, () => console.log(this.state))
}
render(){
if (this.state.edit === false) {
return (
<UsersList
users = {this.state.users}
displayList = {this.state.displayList}
handleClick = {this.handleClick}
/>
);
}
else {
this.getUserEdit();
return(
<UserEdit
user = {this.state.userEdit}
displayForm = {this.state.displayForm}
handleChange = {this.handleChange}
handleClick = {this.handleClick}
/>
)
}
}
}
export default Users;
//UserEdit.js code
import React from 'react';
function UserEdit(props){
return(
<ul>
<div style={{display: props.displayForm.form}} key={props.user.id}>
<form>
<h2>{props.user.name} </h2>
<p>Email:
<input
type="text"
name="email"
value = {props.user.email}
className="form-control"
onChange={props.handleChange}
/>
</p>
<p>Address: </p>
<ul>
<li>Street:
<input
type="text"
name="address.street"
value={props.user.address ? props.user.address.street : ''}
className="form-control"
onChange={props.handleChange}
/>
</li>
<li>Suite:
<input
type="text"
name="address.suite"
value={props.user.address ? props.user.address.suite : ''}
className="form-control"
onChange={props.handleChange}
/>
</li>
<li>City:
<input
type="text"
name="address.city"
value={props.user.address ? props.user.address.city : ''}
className="form-control"
onChange={props.handleChange}
/>
</li>
<li>ZipCode:
<input
type="text"
name="address.zipcode"
value={props.user.address ? props.user.address.zipcode : ''}
className="form-control"
onChange={props.handleChange}
/>
</li>
</ul>
<p>Phone:
<input
type="text"
name="phone"
value = {props.user.phone}
className="form-control"
onChange={props.handleChange}
/>
</p>
</form>
<button onClick={() => props.handleClick()}> Save </button>
<hr></hr>
</div>
</ul>
)
}
我试图放在控制台上看看会发生什么。例如,街道名称是"Kulas Light",如果我单击数字 5,输入保持不变,但控制台显示为"Kulas Light5">
代码沙盒
更新 #1:在问题中提供的代码沙箱之后:
工作解决方案。 从问题中提供的原始代码分叉而来。
- 所做的唯一编辑是
Users.js
- 按照评论找出发生了什么。
远离主要问题:
- 保存功能不完整,因为它似乎实际上没有对数据执行任何 POST 操作
除了来自克里斯托弗的通知之外,您还需要编辑您所在州输入的确切值,例如:
如果您正在编辑name
属性,则需要在状态userEdits
中更新它。
handleChange(event){
const newUserEdit = {...this.state.userEdit};
this.setState({
...this.state,
userEdit: {
...newUserEdit,
[event.target.value]: event.target.value
}
}, () => console.log(this.state))
}
只有当你的输入没有这样的名称时,这段代码才会真正起作用,比如:address.zipcode
address.suite
我对接受此类名称并将其转换为可读userEdit.address.name
的handleChange
进行了小编辑:
handleChange(event){
const newUserEdit = {...this.state.userEdit};
const { value, name } = event.target; //get name and value out of event.target
if(name.indexOf('address.')){
newUserEdit = {
...newUserEdit,
address: {
[name.split('.')[1]]: value
}
}
} else {
newUserEdit = {
...newUserEdit,
[name]: value
}
}
this.setState({
...this.state,
userEdit: { ...newUserEdit }
}, () => console.log(this.state))
}
您的handleChange()
将父状态中的对象设置为单个字段。
handleChange(event){
var change = {}
change[event.target.name] = event.target.value
this.setState(change) //change only has one key-value pair, whereas initially state had multiple key-values
console.log(change)
}
使用展开运算符{...}
保留组件的现有状态。从本质上讲,传播只是意味着获取所有现有数据(键值级(并在新对象中使用它们。您可以改为将handleChange()
修改为以下内容:
handleChange(event){
this.setState({
...this.state,
[event.target.name]: event.target.value
}, () => console.log(this.state) )
}
此外,this.setState()
还有第二个接受回调函数的参数。在该回调中,我们可以访问更新状态。因此,在您的活动成功完成后,我们可以读取新数据。
在你的句柄更改中,你每次都会将状态设置为一个新对象,这会破坏现有状态。
通过您对问题所做的编辑,这是它可能看起来的样子。在每个实例中,我都会使用您的输入名称动态设置特定的状态键,并为其分配输入值。由于状态的设置方式,您必须检查输入名称是什么,以指导更新状态的正确部分。
handleChange = ({ target: { name, value } }}) => {
if (['street', 'suite', 'city', 'zipcode'].includes(name)) {
this.setState(prev => ({
userEdit: {
...prev.userEdit,
address: { ...prev.userEdit.address, [name]: value }
}
}));
} else {
this.setState(prev => ({
userEdit: { ...prev.userEdit, [name]: value }
}));
}
}
这也意味着将您的地址输入名称更改为简单的"city"而不是"address.city"。
下面是使用代码的沙盒。
另请注意,由于setState
通常是异步的,因此无法立即记录新状态。 setState
有一个可以改用的回调。
handleChange(event) {
this.setState(this.setState({ userEdit: { [name]: value } },
() => console.log(this.state)
);
}