React JS - 用动态子项组成通用表单

时间:2017-05-31 06:57:10

标签: forms reactjs input components composition

我只是reactjs的初学者。我对使用它感觉非常好,但是我已经坚持了一段时间我想要实现的概念,这将解决我很多其他问题。

概念

  • 我想创建一个可以将动态子项传递给它的表单组件。它不会是一个特定的表单组件,如 LoginForm,ContactForm 等。它只是表单

方法1

class LoginPage extends Rect.Component {

    constructor(props) {
        super(props)

        this.submit = this.submit.bind(this);
        this.validate = this.validate.bind(this);
        this.reset = this.reset.bind(this);
    }

    submit(...args) {
        this.refs.form.submit(args);
    }

    validate(...args) {
        this.refs.form.validate(args);
    }

    reset(...args) {
        this.refs.form.reset(args);
    }

    render() {
        return (
        <LoginPage>
            <Form ref="form" onSubmit={this.submit}>
                <Input value="email" pattern="/email_pattern/" onValidate={this.validate} />

                <Input value="password" pattern="/password_pattern/" onValidate={this.validate} />

                <Button value="submit" action={this.submit} />
                <Button value="reset" action={this.reset} />
            </Form>
        </LoginPage>
    }
}
  • 输入onChange调用validate函数,该函数只将args传递给Form的validate函数。为表格知道它的所有孩子是否都经过验证。我将isValid和targetInputComponent作为args传递给表单。
  • 按钮提交onClick同样调用提交函数,而LoginPage(充当中间件)将调用传递给Form组件。表格检查inValid输入等的状态。
  • 按钮重置onClick调用同样传递给Form组件。但是表单如何处理此重置功能?输入的值由LoginPage控制。表格不能改变输入的值。

Aproach 2

我所做的是将输入的数据和有效性添加到LoginPage状态。现在,Form和Input都调用Login Page来更新它的状态。表单和输入组件使用此状态作为prop。

class LoginPage extends React.Component {

    constructor(props) {
        super(props)

        this.state = {
            formSchema: this.initSchema()
        }

        this.validateField = this.validateField.bind(this);
        this.submitForm = this.submitForm.bind(this);
    }

    initSchema() {
        const formSchema = {
            email: {
                isValid: false,
                value: ''
            },
            password: {
                isValid: false,
                value: ''
            },
            password2: {
                isValid: false,
                value: ''
            }
        }

        return formSchema;
    }

    validateField(dataObj, targetComponent) {

        const formSchema = Object.assign(this.state.formSchema, dataObj);

        this.setState({ formSchema })
    }

    submitForm(isSuccess) {
        console.log(isSuccess);
        console.log('Form Submit: ', this.state.formSchema);

        throw new Error('Submition Error');
    }

    reset() {
        // Loop through each object in formSchema and set it's value to empty, inputs will validate themselves automatically.
    }

    render() {
        return <div>
            <Form ref="formLogin" className="auth-form" onSubmit={this.submitForm} formSchema={this.state.formSchema}>
                <h1>
                    Switch Accounts
                </h1>
                <Input type="email" name="email" onValidate={this.validateField} value={this.state.formSchema.email.value}
                isValid={this.state.formSchema.email.isValid}/>

                <Input type="password" name="password" onValidate={this.validateField} value={this.state.formSchema.password.value}
                isValid={this.state.formSchema.password.isValid}/>

                <Button value="Submit" type="submit"  />
            </Form>
        </div>
    }
}

问题

这种方法使得LoginPage组件非常混乱。如果页面上有多个表单,LoginPage组件将如何处理表单? LoginPage还有更多功能,如列表,网格,模态等。此LoginPage不应处理这些情况。 表单应该负责所有输入,submition等功能。此表单组件应对所有类型的表单都是通用的。我不想创建像LoginForm,ContactForm等功能表单。

这个问题的解决方案将帮助我很多其他组件。

2 个答案:

答案 0 :(得分:1)

您的方法2是处理此问题的标准方法。

为什么不创建单独的<LoginForm>?这样做可以将字段和验证从页面上的其他不相关的功能中抽象出来。

如果以后需要<ContactForm>或任何其他类型的表单,它将具有不同的字段和不同的验证逻辑,这意味着无论如何都需要构建它。

如果没有使用像redux那样的东西,那么你就是在正确的轨道上。

答案 1 :(得分:1)

有很多方法可以生成“通用”表格。但我认为最好分开保存表格。

之所以这样说,是因为您仍然必须对大多数字段实施各种验证条件,例如电子邮件地址或将要使用的内容。

我认为最好的方法是使组件独立。例如:创建一个TextField组件来处理诸如验证之类的输入内容。也许是用于提交和回调的Button组件。

所以我的建议是:使表格分开。无需为使事情变得“漂亮”而思考并浪费有用的时间。

祝你好运!