简体   繁体   English

OnChange 不保存 setState 上的写入输入值

[英]OnChange not saving the written input value on setState

This seems a silly question, so I apologize in advance.这似乎是一个愚蠢的问题,所以我提前道歉。

I have a page with several inputs and at the moment, for some reason, I can't just get the new value written in the input, so I can update the state and send this new data.我有一个包含多个输入的页面,目前,出于某种原因,我不能只在输入中写入新值,因此我可以更新状态并发送此新数据。 Seems to me there is something wrong in with the onChange function, because I can get the previous state, but not the new value i'm saving on state.在我看来 onChange 函数有问题,因为我可以获得以前的状态,但不能获得我在状态上保存的新值。

EDIT: The submit button is outside the input form.编辑:提交按钮在输入表单之外。

Here is the code:这是代码:

constructor(props) {
    super(props)

    this.state = {
        editMode: false,
        data: {
            designation: '', 
            address: '', 
            description: ''
        }
    }
}

componentDidMount = () => {
    const dataInfo = data.get('url here');//fetching data here

    const data = {
        designation: dataInfo.designation , 
        address: dataInfo.address, 
        description: dataInfo.description 
    }

    this.setState({
        data: data
    })
}

handleInput = (e) => {
let value = e.target.value;
let name = e.target.name;

this.setState(
  prevState => ({
    data: {
      ...prevState.data,
      [name]: value
    }
  })
);
}

handleFormSubmit = (e) => {
    e.preventDefault();

    const { data } = this.state;

    console.log('hey', data.designation);

    this.setState({
        editMode: false
    })
 }

   render() {

   {!this.state.editMode 
? <button onClick={() => this.setState({ editMode: true })}>edit</button> 
: <div>
   <button 
   className={styles.buttonMargin} 
   onClick={() => this.setState({ editMode: false })}>cancel</button>
   <button onClick={this.handleFormSubmit}>Guardar</button>
  </div> 
    }

    <div>
      {this.state.editMode 
    ? <form onSubmit={this.handleFormSubmit}>
      <input 
        type='text'
        placeholder='Nome do Campo' 
        name='designation' 
        onChange={this.handleInput} 
        defaultValue={this.state.data.designation}
      />
      </form>
    : <p> {this.state.data.designation} </p> }
    </div>
 }
}

There are a number of changes that I would recommend, I have a working version of your code here: https://stackblitz.com/edit/react-vmeuxc我建议进行许多更改,我在这里有您的代码的工作版本: https : //stackblitz.com/edit/react-vmeuxc

Binding your functions inside of constructor will allow you to write unit tests later and also access the functions from outside of your component if needed.在构造函数内部绑定函数将允许您稍后编写单元测试,并在需要时从组件外部访问函数。

In my experience, using e.currentTarget.value is more stable than using e.target.value Difference between e.target and e.currentTarget根据我的经验,使用e.currentTarget.value比使用e.target.value更稳定e.target 和 e.currentTarget 之间的区别

I didn't see why you were assigning this.state to a constant in handleFormSubmit so I removed that.我不明白为什么你被分配this.state以在恒定handleFormSubmit所以我删除了。

You were missing some markup, such as a submit button on your form and an edit button when you weren't in the edit mode.您缺少一些标记,例如表单上的提交按钮和未处于编辑模式时的编辑按钮。 I also don't understand why you had the random this.setState({ editMode: false }) at the end of your render statement, so I removed that since it wasn't necessary.我也不明白为什么你在render语句的末尾有随机this.setState({ editMode: false }) ,所以我删除了它,因为它没有必要。

Having a helper function such as this would help to examine the existing value to the new one.拥有这样的辅助函数将有助于检查新值的现有值。

  compareData(currentData, newData) {
    if(currentData === 'undefined' || (newData && currentData !== newData)) {
      return newData;
    } else {
      return false;
    }
  }

Here's the fully cleaned up version of your code.这是您的代码的完全清理版本。 Note: I had to create a dummy dataInfo object since I don't have access to your API.注意:我必须创建一个虚拟的dataInfo对象,因为我无权访问您的 API。

  constructor(props) {
    super(props);
    this.compareData = this.compareData.bind(this);
    this.handleInput = this.handleInput.bind(this);
    this.handleFormSubmit = this.handleFormSubmit.bind(this);
    this.state = {
      editMode: false,
      data: {
        designation: '', 
        address: '', 
        description: ''
      }
    }
  }

  componentDidMount = () => {
    const dataInfo = {
      designation: 'test designation',
      address: 'test address',
      description: 'test description'
    };
    // const dataInfo = data.get('url here'); //fetching data here
    const data = {
      designation: dataInfo.designation , 
      address: dataInfo.address, 
      description: dataInfo.description 
    }

    this.setState({
        data: data
    })
  }

  compareData(currentData, newData) {
    if(currentData === 'undefined' || (newData && currentData !== newData)) {
      return newData;
    } else {
      return false;
    }
  }

  handleInput(e) {
    let value = e.currentTarget.value;
    let name = e.currentTarget.name;

    if(this.compareData(this.state.data[name], value)) {
      this.setState({
        data: {
          ...this.state.data,
          [name]: value
        }
      });
    }

    console.log(this.state);
  }

  handleFormSubmit(e) {
    e.preventDefault();

    this.setState({
      editMode: false
    });
  }

  render() {
    return (
      <div>
        {!this.state.editMode ? (
          <button onClick={() => this.setState({ editMode: true })}>edit</button> 
        ) : (
          <div>
            <button onClick={() => this.setState({ editMode: false })}>cancel</button>
            <button onClick={this.handleFormSubmit}>Guardar</button>
          </div> 
        )}

        {this.state.editMode ? (
          <form>
            <input 
              type='text'
              placeholder='Nome do Campo' 
              name='designation' 
              onChange={this.handleInput} 
              defaultValue={this.state.data.designation}
            />
          </form>
        ) : (
          <p> {this.state.data.designation} </p>
        )}
      </div>
    )
  }

i tweaked your code a little bit.我稍微调整了你的代码。 In my case is working, although i suggest you to use value instead of defaultValue for setting the value content of the input component.在我的情况下,虽然我建议您使用 value 而不是 defaultValue 来设置输入组件的值内容。 I had to declare a dummy object instead of fetching the data, and declare your component as a standard HTML field.我必须声明一个虚拟对象而不是获取数据,并将您的组件声明为标准 HTML 字段。 Also i added a button to enable edit mode since i don't get in which moment you do that.我还添加了一个按钮来启用编辑模式,因为我不知道你在哪个时刻这样做。 You can test it in codesandbox io (link to working example is https://codesandbox.io/s/n4lpz784wj ):您可以在 codesandbox io 中对其进行测试(工作示例的链接是https://codesandbox.io/s/n4lpz784wj ):

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class App extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      editMode: false,
      data: {
        designation: '',
        address: '',
        description: ''
      }
    }
  }

  componentDidMount = () => {
    //const dataInfo = data.get('url here');//fetching data here
    const dataInfo = {
      designation: "Do something else",
      address: "5th Avenue #45",
      description: "This is a test description"
    }
    const data = {
      designation: dataInfo.designation,
      address: dataInfo.address,
      description: dataInfo.description
    }

    this.setState({
      data: data
    })
  }

  handleInput = (e) => {
    let value = e.target.value;
    let name = e.target.name;

    this.setState(
      prevState => ({
        data: {
          ...prevState.data,
          [name]: value
        }
      })
    );
  }

  toggleEditionMode = () => {
    this.setState({ editMode: true});
  }

  handleFormSubmit = (e) => {
    e.preventDefault();

    const { data } = this.state;

    console.log('hey', data.designation);

    this.setState({
      editMode: false
    })
  }

  render() {
    console.log(this.state.data.designation);
    return (
    <div>
      {this.state.editMode
        ? <form onSubmit={this.handleFormSubmit}>
          <input
            type='text'
            placeholder='Nome do Campo'
            name='designation'
            onChange={this.handleInput}
            defaultValue={this.state.data.designation}
          />

        </form>
          : <p> {this.state.data.designation} <button type="button" onClick={this.toggleEditionMode}>Enable edit</button> </p>}
    </div>
    );
  }

}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM