Forms React JS-使用动态子对象编写通用表单

Forms React JS-使用动态子对象编写通用表单,forms,reactjs,input,components,composition,Forms,Reactjs,Input,Components,Composition,我只是一个初学者。我对使用它感觉很好,但我已经在一个我想要实现的概念上停留了一段时间,这将解决我所有的其他问题 概念 我想创建一个表单组件,可以将动态子元素传递给它。它不会是一个特定的表单组件,如LoginForm、ContactForm等。它只会是form 方法1 class LoginPage extends Rect.Component { constructor(props) { super(props) this.submit = thi

我只是一个初学者。我对使用它感觉很好,但我已经在一个我想要实现的概念上停留了一段时间,这将解决我所有的其他问题

概念

  • 我想创建一个表单组件,可以将动态子元素传递给它。它不会是一个特定的表单组件,如LoginForm、ContactForm等。它只会是form
方法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>
    }
}
classloginpage扩展了Rect.Component{
建造师(道具){
超级(道具)
this.submit=this.submit.bind(this);
this.validate=this.validate.bind(this);
this.reset=this.reset.bind(this);
}
提交(…args){
此.refs.form.submit(args);
}
验证(…args){
this.refs.form.validate(args);
}
重置(…args){
此.refs.form.reset(args);
}
render(){
返回(
}
}
  • Input onChange调用validate函数,该函数只将参数传递给窗体的validate函数。为了让窗体知道是否所有子项都已验证,我将isValid和targetInputComponent作为参数传递给窗体
  • 按钮Submit onClick同样调用Submit函数,LoginPage(充当中间件)将调用传递给表单组件。表单检查其状态是否存在无效输入等
  • 按钮重置onClick调用同样会传递给表单组件。但是表单如何处理此重置功能?输入值由LoginPage控制。表单无法更改输入值
Aproach 2

我所做的是将输入的数据和有效性添加到登录页面状态。现在,表单和输入都只调用登录页面来更新其状态。表单和输入组件将此状态用作属性

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>
    }
}
class LoginPage扩展了React.Component{
建造师(道具){
超级(道具)
此.state={
formSchema:this.initSchema()
}
this.validateField=this.validateField.bind(this);
this.submitForm=this.submitForm.bind(this);
}
initSchema(){
const formSchema={
电邮:{
isValid:false,
值:“”
},
密码:{
isValid:false,
值:“”
},
密码2:{
isValid:false,
值:“”
}
}
返回formSchema;
}
validateField(数据对象、目标组件){
const formSchema=Object.assign(this.state.formSchema,dataObj);
this.setState({formSchema})
}
提交表格(isSuccess){
控制台日志(isSuccess);
log('formsubmit:',this.state.formSchema);
抛出新错误(“提交错误”);
}
重置(){
//循环遍历formSchema中的每个对象并将其值设置为空,输入将自动进行验证。
}
render(){
返回
转换帐户
}
}
问题

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


这个问题的解决方案将在许多其他组件中对我有很大帮助。

您的方法2是处理这个问题的标准方法

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

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


除了使用诸如
redux
之类的工具外,您的做法是正确的。

制作“通用”表单的方法有很多。但在我看来,最好将表单分开保存

我之所以这样说,是因为无论如何,您仍然必须为大多数字段实现各种验证条件,例如电子邮件地址或您将使用的任何字段

我认为最好的方法是使组件个性化。例如:制作一个TextField组件来处理诸如验证之类的输入内容。可能是一个用于提交和回调的按钮组件

因此,我的建议是:保持形式的独立性。在试图使事物变得“漂亮”时,不需要过度思考和浪费有用的时间


祝你好运!

感谢兄弟的澄清。我现在开始第二个aproach。这感觉更容易管理。另外,单独表单的问题是,我还将创建一个动态列表组件,该组件可以将表单作为列表项。而且这些表单将具有动态字段。我不知道这一点。所以我不能不要创建单独的表单。React只是一个非常轻量级的视图层,组件状态作为道具层叠而下,作为回调而备份。有
setState
,但不幸的是,除了简单的内部组件状态之外,它的可伸缩性不强。您所描述的需要使用全局状态存储。Lo如我所述,可以进入redux,或者
mobX
哪个更直观