React表单错误更改类型文本的受控输入是不受控制的

时间:2017-03-05 09:25:48

标签: reactjs

我正在使用受控输入创建一个简单的表单。在我的组件状态中,我有2个属性" clientName"和"许可证"在国家。改变这些工作正常。但是有一个"运输"作为对象的属性。更改任何运输属性会产生错误。例如,如果我更改" address1",只要在handleShippingChange函数中设置了状态,我就会收到错误:

  

警告:TextField正在更改text类型的受控输入   不受控制。输入元素不应从受控切换到   不受控制的(反之亦然)。决定使用受控制的还是   组件寿命的不受控制的输入元素。

我怀疑这与我如何定义这些TextFields的值以及我如何设置运送属性的状态有关。我究竟做错了什么?我的组件的代码如下:



import React, {Component} from 'react';
    import TextField from 'material-ui/TextField';
    import RaisedButton from 'material-ui/RaisedButton';
    import 'whatwg-fetch';

    class Clients extends Component {
      constructor() {
        super();
        this.state = {
          "clientName": "client name",
          "shipping": {
            "name": "name",
            "address1": "address 1",
            "address2": "address 2",
            "city": "city",
            "state": "state",
            "zip": "zip",
            "country": "country"
          },
          "license": "license"
        };

        this.handleChange = this.handleChange.bind(this);
        this.handleShippingChange = this.handleShippingChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
      };       

      handleChange(event) {
        this.setState({
          [event.target.name]: this.getFieldValue(event.target)
        });
      };

      handleShippingChange(event) {
        this.setState({
          shipping: {
            [event.target.name]: this.getFieldValue(event.target)
          }
        });
      };

      getFieldValue(target) {
        return target.type === 'checkbox' ? target.checked : target.value;
      };

      handleSubmit = (event) => {
        event.preventDefault();

        // do some stuff
      };   

      render() {
        return <div>
          <h1>
            Clients Page
          </h1>

          <form onSubmit={this.handleSubmit}>
            <TextField
              hintText="Enter the client name"
              floatingLabelText="Client Name"
              value={this.state.clientName}
              onChange={this.handleChange}
              name="clientName"
            />
            <h2>Shipping Info</h2>
            <TextField
              hintText=""
              floatingLabelText="Name"
              value={this.state.shipping.name}
              onChange={this.handleShippingChange}
              name="name"
            />
            <br />
            <TextField
              hintText=""
              floatingLabelText="Address Line 1"
              value={this.state.shipping.address1}
              onChange={this.handleShippingChange}
              name="address1"
            />
            <br />
            <TextField
              hintText=""
              floatingLabelText="Address Line 2"
              value={this.state.shipping.address2}
              onChange={this.handleShippingChange}
              name="address2"
            />
            <br />
            <TextField
              hintText=""
              floatingLabelText="City"
              value={this.state.shipping.city}
              onChange={this.handleShippingChange}
              name="city"
            />
            <br />
            <TextField
              hintText=""
              floatingLabelText="State"
              value={this.state.shipping.state}
              onChange={this.handleShippingChange}
              name="state"
            />
            <br />
            <TextField
              hintText=""
              floatingLabelText="Zip Code"
              value={this.state.shipping.zip}
              onChange={this.handleShippingChange}
              name="zip"
            />
            <br />
            <TextField
              hintText=""
              floatingLabelText="Country"
              value={this.state.shipping.country}
              onChange={this.handleShippingChange}
              name="country"
            />
            <br />
            <TextField
              hintText=""
              floatingLabelText="License"
              value={this.state.license}
              onChange={this.handleChange}
              name="license"
            />
            <br />
            <RaisedButton label="OK" primary={true} type="submit" />
          </form>
        </div>
      };
    }

    export default Clients;
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
&#13;
&#13;
&#13;

3 个答案:

答案 0 :(得分:29)

受控/不受控制的输入表示UITextField字段是否包含值。

<input>

这个想法是你不想从受控输入改变到不受控制的输入。两种类型的输入都有不同的行为,这可能会导致错误和/或不一致。

最简单的解决方法是确保始终存在默认值(对于空字段,默认值为空字符串// This is a controlled input <input value="foo"/> // This is an uncontrolled input <input value={null}/> )。

另外,请注意,一致类型通常优于可空类型,因为您可以保证某个值的类型。这有助于减少由于空检查(''

导致的开销

但是如果你只想要一行修复,你也可以在jsx中提供内联的默认值:

if (val != null) { /* ...etc */ }

答案 1 :(得分:3)

根本问题在于我在发货对象上设置属性的方式,它不会将新属性值与原始属性值合并。因此,对于我正在编辑的TextField,警告并非如此,而是其他运送的TextFields正在被吹走。我不确定这是否是可以接受的做法,因为很难找到你在该州使用某个对象的例子。但是,将handleShipping方法更改为此修复了我的问题:

handleShippingChange(event) {
  var shipping = this.state.shipping;
  shipping[event.target.name] = this.getFieldValue(event.target);

  this.setState({
    shipping: shipping
  });
};

基本上,我是从州创建现有装运对象的副本,更改它并将整个装运对象设置为等于更改后的副本。

答案 2 :(得分:0)

我刚刚遇到了同样的问题,但事实证明错误更简单(边缘线令人尴尬)

我在定义onChange函数时忘了添加event参数。

handleChange(event) {
  ...          ^-this
};

奇怪的是我没有收到event is undefined错误...希望这有助于某人。