javascript - 存储可重用的 React+Flux 表单组件(一个组件用于具有不同字段的多个表单)

标签 javascript reactjs reactjs-flux flux

在我正在开发的应用程序中,我有几个具有不同字段的不同表单。我想创建一个可重用的组件用于每种表单。

  • 表单 #1 可能包含以下字段:电子邮件、密码
  • 表单 #2 可以包含以下字段:移动消息、平板电脑消息、桌面消息、背景颜色、文本颜色

对于这个例子——假设我使用的是 Form #1;这是我针对该用例的代码:

var LoginForm = React.createClass({
    handleSubmit: function(){
        var formValues = {
            username: '',
            password: '',
            url:      '/api/login/'
        };

        // Submit form, whee!
        FormActions.submit(formValues);
    },
    render: function(){
        var formSections = [
            {
                name: 'Sign in here',
                fields: [
                    {
                        name: 'username',
                        label: 'Username',
                        type: 'text'
                    },
                    {
                        name: 'password',
                        label: 'Password',
                        type: 'password'
                    }
                ]
            }
        ];
        return (
            <FormComponent sections={formSections} handleSubmit={this.handleSubmit} />
        );
    }
});

因此,我希望能够向我的 FormComponent 传递一个包含表单部分(其中包含字段)的数组。表单部分的示例包括:个人信息、送货地址、账单详细信息。

我想要弄清楚的是,如何生成一个“通用”Flux 存储来处理我扔给它的任何表单字段。例如,在我的 formSections 数组中,我希望能够传递不同的字段并仍然利用 Flux 架构。

我不确定的是我使用这种模式是否犯了错误;我是否应该为我将使用的每种类型的表单创建一组不同的操作、常量、存储等?或者创建一个能够在单个 FormComponentStore 存储中处理不同字段的表单组件是一种可靠的做法吗?

最佳答案

我已经在 React/Flux 中实现了类似的东西,并且对结果非常满意,尽管它对于您整体使用来说可能有点太专业了。我将简要介绍一下移动部分,您可以决定是否喜欢该方法以及哪些部分可能适合您的需求。基本思想是能够生成 Form DOM 及其从配置 block 与 API 的不同部分进行通信所需的行为。首先,这是我实例化 BasicAPIForm 的方法,它是一个由 Flux“FormStore”支持的有状态组件:

参见code :

render: function(){
  var formProps = {
    formId: "uniqueFormId1",
    fieldsMeta: {
      name: {inputType: "text", label: "Name", required: true},
      description: {inputType: "textarea", label: "Description", required: true},
      url: {inputType: "text", label: "Website URL", required: true},
      email: {inputType: "text", label: "Contact Email", required: true},
      image: {inputType: "image", label: "Logo", required: false, filename: "logo.png"}
    },
    defaultValues: {
      name: "",
      description: "",
      url: "",
      email: "",
      image: null,

      imageData: null,
      actionState: "ready",
      message: ""
    },
    columns: [
      { fields: ['image'], className:'col-xs-5 col-sm-4 col-md-3' },
      { fields: ['name', 'description', 'url', 'email'], className:'col-xs-7 col-sm-8 col-md-9' }
    ],
    apiContext: {
      formId: this.props.type,
      apiCollectionKey: "theRightCollection",
      actionUrl: "/v1/resource/items",
      method: "POST",
      successHttpStatus: [201],
      successMessage: "New resource created"
    }
  };
  FormStore.getOrInitFormData(this.props.type, formProps);

  return (
    <div className="active-panel api-form image-upload-form clearfix">
      <div className="container-fluid">
        <BasicAPIForm {...formProps} />
      </div>
    </div>
  );
}

BasicAPIForm组件需要一个唯一的 formId、它可以理解的字段列表(例如,图像上传字段需要像 filename 这样的属性)、一些初始状态( >defaultValues),一些关于如何将字段分组为列的配置,然后是一个类似的 API 配置对象,帮助 APIStore 构建 API 请求并处理响应。正如我所实现的那样,BasicAPIForm 是一个具有很多行为的复杂组件。对于每种不同类型的输入(例如“图像”),我必须创建一个组件。在 BasicAPIForm 的 render() 方法中,它基本上会遍历列,根据配置和当前状态渲染每一列中的字段。这是一个“托管”表单,因此每次更改 DOM 输入时,它都会更新自己的状态并与 FormStore 同步。

FormStore如调用 FormStore.getOrInitFormData(this.props.type, formProps) 中所示,与应用程序上所有事件表单的状态保持同步。这可能是不需要的;您可以将所有状态保留在组件中。

APIStore在我们的实现中,负责管理前端应用程序已知的数据并与服务器通信以获取或发布所需的数据。 APIStore 监听表单 POST 操作,从 FormStore 获取相关输入和 API 配置,向 API 发送请求,存储结果,并在完成时创建 FormStore(和表单组件)可以接收的成功或失败操作显示结果。

在我们的 FormStore 实现中,当 BasicAPIForm 上发生状态更改时,FormStore 中的表示会被修补。为不同的表单存储不同的数据没有任何障碍,只要数据基本上看起来像一个 JSON {} 对象,并且表单有一个唯一的键,该键随对 FormStore 的所有调用一起传递。起初,我在 Store 中存储默认值和类型,但扩展性不佳,因此我将其移动到上面的这个大配置 blob,该配置 blob 可以非常接近相关的渲染代码。 future 肯定会有一些重大的变化。

这种方法在我们的项目中不断发展。到目前为止,第一次构建花费了很长的时间,但每次后续的重构和添加的新表单花费的时间越来越少,所以总体来说,它似乎越来越富有成效。这证明了在表单中加入高度的交互性和润色是合理的。

关于javascript - 存储可重用的 React+Flux 表单组件(一个组件用于具有不同字段的多个表单),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30058469/

相关文章:

javascript - 如何在 TypeScript 中读取 "transpose"对象

javascript - 使用 TypeScript 和 React-Redux 时推断映射的 Prop

reactjs - 如何使 react 选择选项可滚动

reactjs - Flux waitFor() 和异步操作,如何建模。

reactjs - React-router、JWT Cookie、Flux、身份验证和 SSR

javascript - 使用 Angular Universal 延迟加载外部 JS 文件

javascript - 如何将图像 (byte[]) 从 servlet 发送到 HTML 页面

javascript - 如何使用 ng-repeat 选择所有元素,但没有一些类

javascript - 制作高阶组件以与 TypeScript 互操作 react-relay 和 react-router

javascript - 调度程序未在 Jest 单元测试中注册回调