句柄在反应上更改函数的问题



我是新手,我对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.namehandleChange进行了小编辑:

  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)
  );
}

最新更新