React Form Textboxes不会在击键之间保持数据

时间:2017-03-21 13:58:24

标签: javascript reactjs

我在这里做错了什么?下面的表格工作正常,直到我开始接线状态。如果我断点或记录代码,我可以看到'this.state.data.xxx'的值在事件方法调用上被更改,但数据随后立即从文本框中清空,并且不会保留。我只能认为我在某处做错了什么。

export default class RegistrationForm extends React.Component {

    constructor(props) {
        super(props);
        this.state = { 
            data: {},
            employersLookupData: []
        };

        this.employersDataSource = new LookupRestServiceGateway("/api/lookups/employers/");

        this.handleEmailChange = this.handleEmailChange.bind(this);
        this.handlePasswordChange = this.handlePasswordChange.bind(this);
        this.handleConfirmPasswordChange = this.handleConfirmPasswordChange.bind(this);
        this.handleFirstNameChange = this.handleFirstNameChange.bind(this);
        this.handleLastNameChange = this.handleLastNameChange.bind(this);
        this.handleEmployerChange = this.handleEmployerChange.bind(this);
    }

    handleEmailChange(e) {
        console.log(this);
        this.state.data.email = e.target.value;
    }

    handlePasswordChange(e) {
        this.state.data.password = e.target.value;
    }

    handleConfirmPasswordChange(e) {
        this.state.data.confirmPassword = e.target.value;
    }

    handleFirstNameChange(e) {
        this.state.data.firstName = e.target.value;
    }

    handleLastNameChange(e) {
        this.state.data.lastName = e.target.value;
    }

    handleEmployerChange(e) {
        this.state.data.employerID = e.target.value;
    }

    loadLookupData() {
        this.employersDataSource.getListItems({ successCallback: (data) => {
            this.setState({ employersLookupData: data ? data.items : [] });
        }});
    }

    componentDidMount() {
        this.loadLookupData();
    }

    render() {                                                                  
        return (
            <Form.Wrapper formId = "registration-form"
                          className = "form-horizontal"
                          onSubmit = {this.onSubmit}
                          onSubmitSuccess = {this.onSubmitSuccess}>
                <h4>Create a new account.</h4>
                <hr/>
                <Form.Line name = "Email" 
                           label = "Email" 
                           type = "email"
                           inputClassName = "col-md-10 col-sm-9" labelClassName = "col-md-2 col-sm-3"
                           value = {this.state.data.email || ""}
                           onChange = {this.handleEmailChange} />
                <Form.Line name = "Password" 
                           label = "Password" 
                           type = "password"
                           inputClassName = "col-md-10 col-sm-9" labelClassName = "col-md-2 col-sm-3"
                           value = {this.state.data.password || ""}
                           onChange = {this.handlePasswordChange} />
                <Form.Line name = "ConfirmPassword" 
                           label = "Confirm Password" 
                           type = "password"
                           inputClassName = "col-md-10 col-sm-9" labelClassName = "col-md-2 col-sm-3"
                           value = {this.state.data.confirmPassword || ""}
                           onChange = {this.handleConfirmPasswordChange} />
                <Form.Line name = "FirstName" 
                           label = "First Name" 
                           inputClassName = "col-md-10 col-sm-9" labelClassName = "col-md-2 col-sm-3"
                           value = {this.state.data.firstName || ""}
                           onChange = {this.handleFirstNameChange} />
                <Form.Line name = "LastName" 
                           label = "Last Name" 
                           inputClassName = "col-md-10 col-sm-9" labelClassName = "col-md-2 col-sm-3"
                           value = {this.state.data.lastName || ""}
                           onChange = {this.handleLastNameChange} />
                <Form.DropDownLine name = "EmployerID"
                                   label = "Employer"
                                   inputClassName = "col-md-10 col-sm-9" labelClassName = "col-md-2 col-sm-3"
                                   emptySelection = "Please select an employer&hellip;"
                                   onChange = {this.handleEmployerChange}
                                   items = {this.state.data.employersLookupData}/>                                    
                <Form.Buttons.Wrapper className="col-sm-offset-3 col-md-offset-2 col-md-10 col-sm-9">
                    <Form.Buttons.Submit text = "Register"
                                         icon = "fa-user-plus" />
                </Form.Buttons.Wrapper>     
            </Form.Wrapper>                                                                                                                  
        );
    }
}

为了完整起见,Form.Line引用了下面的FormLine组件......

export default class FormLine extends React.Component {

    render() {
        let controlClassName = this.props.children 
            ? `form-control ${this.props.controlClassName} noted-form-control`
            : `form-control ${this.props.controlClassName}`;

        return (
            <div className="row padded-row">
                <div className="form-group">
                    <FormLabel name = {this.props.name} 
                               className = {this.props.labelClassName} 
                               value = {this.props.label} />
                    <div className={this.props.inputClassName}>
                        <TextBox name = {this.props.name} 
                                 className = {controlClassName} 
                                 maxLength = {this.props.maxLength} 
                                 value = {this.props.value} 
                                 type = {this.props.type} 
                                 onChange = {this.props.onChange} />
                        <FormInputNotes>{this.props.children}</FormInputNotes>
                    </div>
                </div>
            </div>
        );
    }
}

和TextBox看起来像这样......

export default function TextBox({name = "", value = "", type = "text", className = "", maxLength = 10000, onChange}) {
    return (
        <input type = {type}
               htmlFor = {name} 
               className = {`form-control ${className}`} 
               maxLength = {maxLength} 
               value = {value} 
               onChange = {onChange} />
    );
}

1 个答案:

答案 0 :(得分:2)

我认为你的问题是你误解了应该改变国家的方式。你这样做:

this.state.data.employerID = e.target.value;

你应该这样做:

let newData = {
  ...this.state.data,
  employerID: e.target.value
}
this.setState({data: newData});

让我们举一个例子:

让我们开始这样的初始状态:

this.state = { someValue: 0 };

执行this.state.someValue = 1不会通知React状态已更改,因此它永远不会渲染。 这是this.setState发生的地方,使用它将通知React Core状态已经改变并需要重新计算(并且也在之后呈现)。以下示例的正确方法是:

this.setState({ someValue: 0 });

在您的情况下,由于您使用的是复杂对象,因此需要替换完整对象,这就是您需要制作副本,更改所需值并使用this.setState更新它的原因。

您的处理程序应该或多或少看起来像这样:

handleFirstNameChange(e) {
  //Create a copy of the original object
  let newData = {
    ...this.state.data,
    //Set the new value
    employerID: e.target.value
  }
  //Set the new value through setState
  this.setState({data: newData});
}

有关React组件的参考或更多信息,请阅读the full docs。如果你有时间,也可以看看组件循环寿命。

让我知道它是否有效。