2017-08-03 7 views
1

まず、ここに私のHOCです:mapDispatchToPropsを正しくメモする方法は?

export default function connectField({ 
     nameProp = 'name', 
     valueProp = 'value', 
     dispatchProp = 'dispatch' 
    }: ConnectOptions) { 

    return compose(
     getContext(contextTypes), 
     connect((state, ownProps) => { 
      const path = [namespace,...getPath(ownProps),...toPath(ownProps[nameProp])]; 
      const value = getOr('', path, state); 
      return { 
       [valueProp]: value 
      }; 
     }, (dispatch,ownProps) => { // <----------- mapDispatchToProps 
      const path = [...getPath(ownProps),...toPath(ownProps[nameProp])]; 

      return { 
       [dispatchProp]: value => dispatch({type: ActionTypes.Change, payload: {path, value}}) 
      }; 

     }, (stateProps, dispatchProps, {[FIELD_PATH]: _, ...ownProps}) => { 
      return {...stateProps, ...dispatchProps, ...ownProps}; 
     }, { 
      areMergedPropsEqual: (a,b) => { 
       let eq = shallowEqual(a,b); 
       console.log('areMergedPropsEqual',a,b,eq); 
       return eq; 
      }, 
     }), 
     withContext(contextTypes, props => { 
      return {[FIELD_PATH]: [...getPath(props), props[nameProp]]}; 
     }), 
    ); 
} 

真ん中に私のmapDispatchToPropsがあります。そのため、毎回新しいアクションクリエーターが作成されているため、areMergedPropsEqualfalseを毎回返します。

私はこのビットをmemoizeする方法を見つけ出すことができません:私は、同じ関数インスタンスを毎回取り戻すよう

value => dispatch({type: ActionTypes.Change, payload: {path, value}}) 

を。

「インスタンスごとのメモアイゼーション」に関するメモがありますが、私がここでやるべきことの頭や尾を作ることはできません。


明確にするために、私は関数をメモする方法を知っています。しかし、私は無限の歴史を持つ大きなキャッシュを使いたくない。不要なメモリ消費です。私はちょうどhow reselect does itのような1のキャッシュサイズが必要です。問題は、「セレクタ」をconnectFieldの中に直接作成することができないということです。つまり、1つの共有インスタンスが作成されます。つまり、すべての「接続フィールド」が同じキャッシュを共有し、互いに上書きして利益を無効にするからです。コンポーネントインスタンスごとにである必要がありますこれは、React-Reduxのconnectメソッドに固有です。セレクタを適切な場所に作成するための構文があり、インスタンスごとに1回しか実行されません。私はAPIの解読に問題があるだけです - オブジェクトを返す関数を返す関数を期待していますか?また、キーとしてpropnameを持ち、値として機能するオブジェクトですか?その関数は何を返しますか?つまり、mapDispatchToPropsオプションで受け入れられるさまざまなバリエーションのすべてについて、ドキュメントでは明確ではありません。

+0

の詳細に関する情報を見ることができます。それは "オブジェクト*または*関数"をとります。関数が1つまたは2つの引数を取る場合は、もう一度別のことを行います。そして、 "高度なシナリオ"の下では、関数は関数を返すこともできると言います。ですから、私は1つの引数をつけて関数に渡し、オブジェクトを返す関数を返すと思います。気にしない限り、私はそれを把握するまでそれを試してみます。 – mpen

+1

私はあなたが探していたものの基盤から外れていることをお詫びします。私は今問題を理解しており、非常に興味深いものです。それについてはまだ考えています...もしあなたが解決策を思いついたら、私は思考を見ることができるように更新してください:) –

答えて

0

既にをお持ちの場合は、memoizeの機能を使用して、任意の機能をメモ機能に変換できます。このmemoized関数は、指定されたパラメータの戻り値を計算し、同じパラメータを提供するそれぞれの戻り値を常に返します。

あなたは、例えば、このようにそれを使用することができます:

import { memoize } from 'lodash' 

const makeChangeDispatcher = memoize((dispatch, path) => 
    value => dispatch({type: ActionTypes.Change, payload: {path, value}}) 
) 

... 

    (dispatch,ownProps) => { // <----------- mapDispatchToProps 
     const path = [...getPath(ownProps),...toPath(ownProps[nameProp])]; 

     return { 
      [dispatchProp]: makeChangeDispatcher(dispatch, path) 
     }; 

    } 

... 

あなたはより密接 `mapDispatchToProps`を読む@KyleRichardson lodash documentation of memoize

+0

私はあなたがポイントを逃したと思います。私が問題を抱えているのは、*インスタンスごとのメモ*です。無限の歴史を持つ単一のグローバルメモ機能を作成しました。それはうまくいくかもしれませんが、私の目標は小道具の変更による再レンダリングを避けることです。そのためには、履歴サイズ1のみが必要ですが、インスタンスごとにする必要があります。申し訳ありませんが、私はそれをより明確にすべきでした。 – mpen

+0

はい、成長の歴史は潜在的な問題になる可能性がありますが、ディスパッチ機能(常に同じ)とコンポーネントの小道具に応じたパスに基づいてメモ機能を提供しています。だからあなたはインスタンスごとに機能を持つでしょう。パス値で正確にミアします。したがって、同じ経路を持つコンポーネントは同じ機能を共有します(問題はありません)。ここで何が間違っていますか?私はその点を逃してしまった^^ –

+0

問題は、小道具が変わるにつれてキャッシュが成長する必要がないということです。私がしようとしているのは、小道具の変更による再レンダリングを避けることだけです。小道具が変わらなければ、私は同じディスパッチ機能を元に戻したい。 doが変更された場合、新しいディスパッチ関数が返されます。そのためには、キャッシュ・サイズが1だけ必要です。 – mpen

関連する問題