简体   繁体   English

将动态表单序列化为对象数组

[英]Serialize dynamic form into array of objects

Here is my initial state in redux 这是我在redux中的初始状态

grains: [{grainId: "", amount: "0.0"}],

Im trying to get my form to serialize to something similar but I cant find a way to have grains be the outer object. 我试图让我的形式序列化到类似的东西,但我找不到办法让谷物成为外部对象。 Im wondering if its even possible or if I'll have to recreate the object manually. 我想知道是否有可能,或者我是否必须手动重新创建对象。 Or just get the state from the store. 或者只是从商店获取状态。

My form looks like this: 我的表格如下所示:

<select
    name='grainId'
    value={this.props.value}
>
 ...options
</select>
<input
    type="text"
    name='amount'
    value={this.props.value}
 />

Then theres an add grain button which will add another object to the array in the state which will then render another section of the form on the page. 然后有一个添加纹理按钮,它将在状态下向数组添加另一个对象,然后将在页面上呈现表单的另一部分。 Is there anyway to wrap each "Grain" section in a form element so that is serializes nicely? 无论如何,是否将每个“谷物”部分包装在一个表单元素中,以便很好地序列化?

If not can I just post the state from the store on form submit or is that bad practice? 如果不能,我可以从商店中将状态发布到表单提交中,还是这种不良做法?

Since you are already loading your initial form data from the redux state, I think it would make sense to have the form update the Redux state as it changes. 由于您已经从redux状态加载了初始表单数据,我认为让表单在Redux状态更改时对其进行更新是有意义的。 With this approach every input chnage would trigger an update of the Redux state, which would then be passed down to the component (through mapStateToProps ), and cause a re-render showing the new value. 使用这种方法,每个输入变更都会触发Redux状态的更新,然后将其向下传递到组件(通过mapStateToProps ),并导致重新渲染以显示新值。 That way you can make sure, in your reducer, that the state always has the shape you prefer ( {grains: [{grainId: "", amount: "0.0"}, etc... ] ). 这样,您可以确保在化{grains: [{grainId: "", amount: "0.0"}, etc... ]器中状态始终具有您喜欢的形状( {grains: [{grainId: "", amount: "0.0"}, etc... ] )。

Like you hinted, that would mean that when you finally submit, you are basically submitting the Redux form state (or at least the props passed down from it). 就像您暗示的那样,这意味着当您最终提交时,您基本上是在提交Redux表单状态(或至少是从其传递的道具)。

That could look something like this (runnable JSFiddle demo here ): 看起来可能像这样( 此处可运行JSFiddle演示 ):

class App extends React.Component {
  renderGrains() {
    const {grains, changeGrain} = this.props;
    return grains.map((grain, index) => (
        <div key={ index }>
          <input
            type="text" 
            value={grain.grainId} 
            onChange={({target:{value}}) => changeGrain(index, 'grainId', value)}
            />
          <input key={ grain.grainId + 'amount' }
            type="number" 
            value={grain.amount} 
            onChange={({target:{value}}) => changeGrain(index, 'amount', value)}
            /> 
          <br />
        </div>
      ));
  }
  render() {
    const {addEmptyGrain, grains} = this.props;
    const onSubmit = (e) => {
        e.preventDefault();
      alert('submitting: \n' + JSON.stringify({grains}, null, 2));
    };
    return (
      <form>
        { this.renderGrains() }
        <button onClick={ (e) => { e.preventDefault(); addEmptyGrain();} }>Add grain</button><br />
        <button onClick={onSubmit}>Submit</button>
      </form>
    );
  }
}

where the reducer would look something like this: 减速器看起来像这样:

const r1_initialState = { grains: [{grainId: "", amount: 0.0}] };
const reducer1 = (state = r1_initialState, action) => {
  switch(action.type) {
    case CHANGE_GRAIN: 
        const {index, key, newValue} = action;
        const grainsCopy = [...state.grains];
      grainsCopy[index][key] = newValue;
        return {...state, grains: grainsCopy};

    case ADD_EMPTY_GRAIN: {
      return {...state, grains: [...state.grains, {grainId: '', amount: 0.0}]}
    }
    default: 
      return state;
  }
};

If this seems like too much work, but you still want to keep the form data in the Redux state, there are libraries like redux-form , which handles the repetitive handling of onChange etc. for your forms. 如果这看起来工作量太大,但是您仍然希望将表单数据保持在Redux状态,那么可以使用redux-form类的库来处理redux-form onChange等的重复处理。

Another option would be to load the initial state from Redux, but just use it to set the internal state of the component. 另一个选择是从Redux加载初始状态,但仅使用它来设置组件的内部状态。 Then handle all the form changes as a change to the component state. 然后将所有表单更改作为对组件状态的更改进行处理。 The same logic as the one in the example above, could be used for rendering the fields from an array. 与上面示例中的逻辑相同的逻辑可用于从数组中渲染字段。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM