我是新来的反应者,并且handleChange函数有问题。 我的程序加载了具有jsonplaceholder数据的用户列表,并具有“编辑”按钮,单击此按钮将显示一个包含所选用户数据的表单。 问题:当我尝试编辑某些字段时,格式为“刷新”。
//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”
答案 0 :(得分:1)
您的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()
还有一个接受回调函数的第二个参数。在该回叫中,我们可以访问更新状态。因此,在您的活动成功完成之后,我们可以读取新数据。
答案 1 :(得分:1)
更新#1: 在问题中提供的codeandbox之后:
Working Solution。就像问题中提供的原始代码一样。
Users.js
远离主要问题:
除了克里斯托弗(Christopher)的通知外,您还需要编辑状态下输入的确切值,例如:
如果您正在编辑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
我对handleChange
进行了小修改,将接受这样的名称并将其转换为可读的userEdit.address.name
:
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))
}
答案 2 :(得分:0)
在handleChange中,每次将状态设置为新对象时都会破坏现有状态。
使用您对问题所做的编辑,这里看起来应该是这样。在每种情况下,我都会使用您的输入名称动态设置一个特定的状态键,并为其分配输入值。由于状态设置方式的原因,您必须检查输入名称是什么,以指导更新状态的正确部分。
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”。
Here's a sandbox using your code。
还请注意,由于setState
通常是异步的,因此您不能立即记录新状态。 setState
有一个您可以改用的回调。
handleChange(event) {
this.setState(this.setState({ userEdit: { [name]: value } },
() => console.log(this.state)
);
}