OnChange不会将书面输入值保存在setState

时间:2019-01-25 15:38:07

标签: javascript reactjs

这似乎是一个愚蠢的问题,所以我提前道歉。

我有一个包含多个输入的页面,由于某种原因,此刻,我不能仅仅将新值写入输入中,因此可以更新状态并发送此新数据。在我看来,onChange函数存在问题,因为我可以获取以前的状态,但无法获取要保存在状态上的新值。

编辑: 提交按钮在输入表单之外。

代码如下:

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

2 个答案:

答案 0 :(得分:1)

我建议您进行一些更改,这里有您的代码的有效版本:https://stackblitz.com/edit/react-vmeuxc

将函数绑定到构造函数内部将使您以后可以编写单元测试,还可以在需要时从组件外部访问函数。

根据我的经验,使用e.currentTarget.value比使用e.target.value Difference between e.target and e.currentTarget

更稳定

我不明白为什么要为this.state中的常量分配handleFormSubmit,所以我删除了它。

您缺少一些标记,例如您不在编辑模式下时的表单上的提交按钮和编辑按钮。我也不明白为什么您在this.setState({ editMode: false })语句的末尾会有随机的render,所以我将其删除了,因为这是不必要的。

具有这样的辅助功能将有助于检查新值的现有价值。

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

这是您的代码的完全清理版本。 注意:由于我无权访问您的API,因此我必须创建一个虚拟dataInfo对象。

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

答案 1 :(得分:0)

我稍微调整了一下代码。就我而言,这是可行的,尽管我建议您使用value而不是defaultValue来设置输入组件的值内容。我必须声明一个虚拟对象而不是获取数据,并将您的组件声明为标准HTML字段。我还添加了一个按钮以启用编辑模式,因为我不知道您在那一刻这样做。您可以在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);