2016-09-27 44 views
0

我有一個Fields組件,我有時嘗試單獨使用它,有時還會使用FieldArray組件。我在下面添加了一個簡化模型片段。FieldArray組件中Redux Form Fields組件的使用

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部件,從內renderSharedComponentfields參數具有以下形式:

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

當我使用Fields成分的FieldArray組件內,從內部的fields參數renderSharedComponent具有以下形式:

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

如果我將在名稱不同的FieldArray組件中使用Fields組件(假設名稱爲paths),則名稱屬性將相應更改(例如, names: [ 'paths[0].value' , 'paths[0].valueIsRegex' ])。

我試圖以一種通用的方式獲取valuevalueIsRegex對象,以支持上面介紹的任何情況。

現在我創建了一個函數,我使用RegEx來確定字段。但是我想知道是否有人知道更好的方法來做到這一點(也許有一個Redux表單實用程序,可能我錯過了閱讀文檔時)。

回答

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> 
 
    ); 
 
};

0

Redux的形式有一個隱藏的實用功能在這裏是有用的,但我不知道你是否能依靠它在未來的版本的可用性:

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

相關問題