2016-09-27 13 views
0

コンポーネントの中から、ときどき使用しようとしているFieldsコンポーネントがあります。私は単純化されたモデルで以下のスニペットを追加しました。FieldArrayコンポーネント内のReduxフォームフィールドコンポーネントの使用

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

Iは、それ自体でFieldsコンポーネントを使用するとき、renderSharedComponent内側からfields引数は以下の形式を有する:

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

IはFieldArray成分、内側からfields引数内部Fieldsコンポーネントを使用renderSharedComponentは、以下の形式を有する。

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

のコンポーネント内にFieldsコンポーネントを別の名前で使用する場合は(たとえばpathsとしましょう)、namesプロパティがそれに応じて変更されます(例: names: [ 'paths[0].value' , 'paths[0].valueIsRegex' ])。

私はvaluevalueIsRegexオブジェクトを一般的な方法で上記のいずれのケースもサポートするようにしようとしています。

今はフィールドを決定するためにRegExを使用する関数を作成しました。しかし、私は誰かがこれを行う良い方法を知っているのだろうかと思っていました(たぶん、Redux Formユーティリティがあり、ドキュメンテーションを読んでいなかったかもしれません)。

答えて

1

同じ問題があります。慣用的な方法は、formValueSelectorfunctionを使用することです。しかし、そのやり方では、セレクタを(私が理解している限り)フォーム全体に通す必要があります。 個人的に私はregexpベースの関数も行いました。ここでは、次のとおりです。

/** 
 
* 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

関連する問題