Record 管理具有许多字段的表单

Record 管理具有许多字段的表单,record,reason,bucklescript,reason-react,Record,Reason,Bucklescript,Reason React,我正在写一份表格。我使用了reducerComponent和一个记录作为状态。假设我有这样的东西: 类型状态={ 字段1:字符串, 字段2:int, }; 类型动作= |SetField1(字符串) |SetField2(int); 让组件=ReasonReact.reducerComponent(“SomeComponent”); 让make=(_children)=>{ …组件, initialState:()=>{field1:,field2:0}, 减速器:(动作,状态)=>开关(动作)

我正在写一份表格。我使用了
reducerComponent
和一个记录作为状态。假设我有这样的东西:

类型状态={
字段1:字符串,
字段2:int,
};
类型动作=
|SetField1(字符串)
|SetField2(int);
让组件=ReasonReact.reducerComponent(“SomeComponent”);
让make=(_children)=>{
…组件,
initialState:()=>{field1:,field2:0},
减速器:(动作,状态)=>开关(动作){
|SetField1(value)=>ReasonReact.Update({…state,field1:value})
|SetField2(value)=>ReasonReact.Update({…state,field2:value})
},
呈现:({state,send})=>
发送(SetField1(getValue(e)))}/>
string_of_int}onChange={e=>send(SetField2(e |>getValue |>int_of_string))}/>
,
}
在本例中,只有2个字段,但是如果有30个字段,如何处理?这是否意味着我必须创建30个不同的操作,并在reducer中处理30次?这是很多无关紧要的代码。有没有办法更动态地修改记录,或者我应该使用另一种状态结构(object,Js.t)

为了澄清,我在两种情况下使用这种形式:

  • 将状态转换为Js.Json.t(使用bs Json)并发送到服务器(使用bs fetch)
  • 使用reason apollo(graphql)作为变体将其发送到服务器

  • 这在很大程度上取决于您的具体需求。您将要对表单数据执行的操作将通知您希望它具有什么形状,您在该组件中还需要执行的操作将通知组件的内部逻辑。但至少有一些想法:

    一种方法是将所有的
    设置字段
    变量组合成一个具有状态更新功能的变量。这样,您就可以在渲染函数中指定要更新的字段:

    类型动作=
    |设置字段(state=>state);
    让make=\u children=>{
    …组件,
    initialState:()=>{field1:,field2:0},
    减速器:(动作、状态)=>
    开关(动作){
    |SetField(更新程序)=>ReasonReact.Update(更新程序(状态))
    },
    呈现:({state,send})=>
    {
    let value=getValue(e);
    send(SetField(state=>{…state,field1:value}));
    }
    }
    />
    {
    让value=e |>getValue |>int_的_字符串;
    send(SetField(state=>{…state,field2:value}));
    }
    }
    />
    ,
    };
    
    但是,因为React事件不是不可变的,并且实际上由React本身重用,所以这很容易出错。这种变通方法增加了冗长。因此,除非你能把这些冗长的内容考虑进去,否则这种方法可能没有多大意义

    如果您在此组件中所做的只是更新状态,则可以完全删除
    操作
    类型。这消除了上面的一些冗长,但在其他方面也有同样的问题,灵活性也要差得多

    let make=\u children=>{
    …组件,
    initialState:()=>{field1:,field2:0},
    减速器:(更新程序,状态)=>
    ReasonReact.Update(更新程序(状态)),
    呈现:({state,send})=>
    {
    let value=getValue(e);
    发送(状态=>{…状态,字段1:value});
    }
    }
    />
    {
    让value=e |>getValue |>int_的_字符串;
    发送(状态=>{…状态,字段2:value});
    }
    }
    />
    ,
    };
    
    谢谢。这是个好主意。为了澄清这一点,我在两种情况下使用了这种形式:-将状态转换为Js.Json.t(使用bs Json)并发送到服务器(使用bs fetch)-将其发送到服务器,使用reason apollo(graphql)作为变体。这种情况下最好的方法是什么?这并不能说明什么,因为您不应该直接根据服务器数据的形状对应用程序状态进行建模,因为这可能会独立于应用程序进行更改,并导致很难修复的错误。应用程序特有的问题更为重要,比如所有表单字段都是文本输入,比如这里的示例,还是不同类型的字段。以及你是否要做任何形式的验证。例如,你是否要根据另一个菜单的选择来过滤一个菜单。一旦添加了所有这些功能,表单字段就不再只是另一个表单字段了。然后每个字段都有一个单独的操作,使得状态转换非常清晰,易于维护。