响应上的handleChange函数的问题

时间:2019-07-18 09:27:24

标签: javascript reactjs

我是新来的反应者,并且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”

CodeSandBox

3 个答案:

答案 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
  • 按照评论找出发生了什么事。

远离主要问题:

  • 保存功能不完整,因为它似乎实际上没有对数据进行任何POST

除了克里斯托弗(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)
  );
}