动态创建表单字段时,反应设置状态不起作用

时间:2018-10-02 08:33:37

标签: reactjs state

我最初用硬编码编写了一个表单,当我使用非常相似的代码时,该表单可以正常工作,但是现在我决定使我的React表单成为动态表单,因此该字段不再更新。

这可能只是我不了解状态如何运作的原因。状态似乎已设置,但在重新渲染时,firstName返回原始值

这是一个简化的版本,我只是尝试用以下方式更新名字

class Test extends Component {
constructor(props) {
    super(props);
    this.state = {
        firstName: 'Fred',
        lastName: 'Smith',
        usrForm: null
    };

    this.formFields = {
        fistName: {
            value: this.state.firstName,
            type: 'text'
        },
        lastName: {
            value: this.state.lastName,
            type: 'text'
        }
    };
}
componentDidMount = () => {
    this.buildForm();
};

updateField = e => {
    this.setState({
        firstName: e.target.value
    });
    this.buildForm();
};

buildForm() {
    const usrForm = Object.keys(this.formFields).map(field => {
        switch (this.formFields[field].type) {
            case 'text':
                return ( <
                    input type = {
                        this.formFields[field].type
                    }
                    value = {
                        this.formFields[field].value
                    }
                    onChange = {
                        this.updateField
                    }
                    />
                );
                // case 'button':
                //     return <button onclick={.....} />
            default:
                break;
        }
    });
    this.setState({
        usrForm: usrForm
    });
}

render() {
    return <div > {
        this.state.usrForm
    } < /div>;
}

}

任何想法?

谢谢

2 个答案:

答案 0 :(得分:0)

I think this happening because the state is not being set incorrectly. In your update field function, you are setting value against firstName which is not where you are reading it from.

constructor(props) {
    super(props);
    this.state = {
        usrForm: null,
        formField: {
            fistName: {
                value: 'Fred',
                type: 'text'
            },
            lastName: {
                value: 'Smith',
                type: 'text'
            }
        }
    };
}

Change your update field to update state according to the field which was not happening earlier. Also, I have moved buildForm to setState callback since it is async.

updateField = (e, field) => {
    const newFormFields = {...this.state.formField};
    newFormFields[field] = { value: e.target.value, type: 'text'}
    this.setState({
        formField: newFormField 
    }, () => {this.buildForm()});
};

Also, update your onChange to call updateField like following

onChange = {(e) => {this.updateField(e, field)}}

(Note: I think you are nesting state too much which is not recommended. Think of simplifying your logic.)

答案 1 :(得分:0)

您应该解决几个问题。例如,您在this.formFields上有一个错字(它是fistName而不是firstName)。另外,您可以使用状态值在构造函数中设置this.formFields。那将仅被调用一次,因此您的值将不会更新。您需要手动更新它们。 还要注意。 setState方法是异步的,因此,如果要在设置状态值后立即使用状态值,则可以在回调中使用它们。

你可以试试吗?

class Test extends Component {
constructor(props) {
    super(props);
    this.state = {
        firstName: 'Fred',
        lastName: 'Smith',
        usrForm: null
    };

    this.formFields = {
        firstName: {
            value: this.state.firstName,
            type: 'text'
        },
        lastName: {
            value: this.state.lastName,
            type: 'text'
        }
    };
}

componentDidMount () {
    this.buildForm();
};

updateField = e => {
    this.setState({
        [e.target.name]: e.target.value
    }, () => this.buildForm());

};

buildForm() {
    const usrForm = Object.keys(this.formFields).map(field => {
        this.formFields[field].value = this.state[field];
        switch (this.formFields[field].type) {
            case 'text':
                return (<
                        input type={
                        this.formFields[field].type
                    }
                              value={
                                  this.formFields[field].value
                              }
                              onChange={
                                  this.updateField
                              }
                              name={field}
                    />
                );
            // case 'button':
            //     return <button onclick={.....} />
            default:
                break;
        }
    });
    this.setState({
        usrForm: usrForm
    });
}

render() {
    return (
        <div> {
            this.state.usrForm
        } </div>

    )

}
}