【问题标题】:Usage of Redux Form Fields component inside a FieldArray component在 FieldArray 组件中使用 Redux Form Fields 组件
【发布时间】:2016-09-27 17:01:49
【问题描述】:

我有一个Fields 组件,我有时尝试单独使用它,有时从FieldArray 组件内部使用它。我在下面添加了一个带有简化模型的 sn-p。

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import { reduxForm, Fields, FieldArray, reducer as formReducer } from 'redux-form';

const reducers = {
  form: formReducer
};

const reducer = combineReducers(reducers);

const store = createStore(reducer);

const renderSharedComponent = (fields) => {
  console.log(fields);
  return (<div>Shared Component</div>);
};

const renderHashes = ({ fields }) => (
  <div>
    {
      fields.map((field) => (
        <Fields
          key={ field }
          names={ [`${field}.value`, `${field}.valueIsRegex`] }
          component={ renderSharedComponent }
        />
      ))
    }
  </div>
);

const ReactComponent = () => (
  <div>
    <FieldArray
      name="hashes"
      component={ renderHashes }
    />
    <Fields
      names={ ['value', 'valueIsRegex'] }
      component={ renderSharedComponent }
    />
  </div>
);

const ReduxForm = reduxForm({
  form: 'default',
  initialValues: {
    hashes: [{}]
  }
})(ReactComponent);

ReactDOM.render((
  <div>
    <Provider store={ store }>
      <ReduxForm />
    </Provider>
  </div>
), document.getElementById('content'));

当我单独使用Fields 组件时,renderSharedComponent 内部的fields 参数具有以下形式:

{
  value: { input: {...}, meta: {...} },
  valueIsRegex: { input: {...}, meta: {...} },
  names: [ 'value' , 'valueIsRegex' ]
} 

当我在FieldArray 组件中使用Fields 组件时,renderSharedComponent 内部的fields 参数具有以下形式:

{
  hashes: [
      {
        value: { input: {...}, meta: {...} },
        valueIsRegex: { input: {...}, meta: {...} }
      }
  ],
  names: [ 'hashes[0].value' , 'hashes[0].valueIsRegex' ]
} 

如果我将在 FieldArray 组件中使用具有不同名称(比如 paths)的 Fields 组件,则名称属性将相应更改(例如 names: [ 'paths[0].value' , 'paths[0].valueIsRegex' ])。

我正在尝试以通用方式获取 valuevalueIsRegex 对象,以支持我上面介绍的任何情况。

现在我已经创建了一个函数,我使用 RegEx 来确定字段。但我想知道是否有人知道更好的方法来做到这一点(也许有一个 Redux Form 工具,我在阅读文档时可能错过了)。

【问题讨论】:

    标签: redux-form


    【解决方案1】:

    有同样的问题。可能惯用的方式是使用formValueSelectorfunction。但是这样它就有点样板了,因为你必须通过表单一直向下传递选择器(据我所知)。 我个人也做了基于正则表达式的函数。这里是:

    /**
     * Converts path expression string to array
     * @param {string} pathExpr path string like "bindings[0][2].labels[0].title"
     * @param {Array<string|int>} array path like ['bindings', 0, 2, 'labels', 0, 'title']
     */
    function breakPath(pathExpr) {
        return pathExpr
            .split(/\]\.|\]\[|\[|\]|\./)
            .filter(x => x.length > 0)
            .map(x => isNaN(parseInt(x)) ? x : parseInt(x));
    }
    
    /**
     * Executes path expression on the object
     * @param {string} pathExpr – path string like "bindings[0][2].labels[0].title"
     * @param {Object|Array} obj - object or array value
     * @return {mixed} a value lying in expression path
     * @example 
     * ```
     * execPath('books[0].title', {books: [{title: 'foo'}]})
     * // yields
     * 'foo' 
     * ```
     */
    function execPath(pathExpr, obj) {
        const path = breakPath(pathExpr);
        if (path.length < 1) {
            return obj;
        }
        return path.reduce(function(obj, pathPart) {
            return obj[pathPart];
        }, obj);
    }
    
    /**
     * A generic GroupLabelField that relies on valueBasePath
     */
    const GroupLabelField = (props) => {
        const groupData = execPath(props.valueBasePath, props);
        return (
            <div className={`label__content label__content_icon_${groupData.objectType.input.value}`}>
                <span className="label__remove"
                      onClick={(e) => { props.handleRemove(); e.stopPropagation(); }}
                >
                    <i className="material-icons material-icons_12 material-icons_top">&#xE5CD;</i>
                </span>
                <span className="label__text">{groupData.title.input.value}</span>
            </div>
        );
    };

    【讨论】:

      【解决方案2】:

      redux-form 有一个隐藏的实用功能,在这里很有用,但我不知道你是否可以依赖它在未来版本中的可用性:

      import structure from "redux-form/lib/structure/plain";
      
      function RenderRow({ names, ...props }) {
        const fields = {};
        names.forEach(n => (fields[n] = structure.getIn(props, n)));
      }
      

      另见this github issue

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-14
        • 2018-09-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多