2017-05-10 5 views
0

このように見えるレデューサーのコードを作成する前に、リストがReact PropsにmapStateToProps経由で正しくマップされていても、再レンダリングされませんでした。コンポーネントを再レンダリングするトリガーとなるもの

case "ADDTOLIST": 
    let stateCopy = Object.assign({}, state); 

    let listsCopy = stateCopy.lists; 
    listsCopy.push(action.item); 

    return {...state, lists: listsCopy}; 

は、その後、私はちょうど私がこれにlistsCopyを設定する行を変更 - 私はリストの配列のコピーを作成するために、スライスを使用:

let listsCopy = stateCopy.lists.slice(); 

そして今、私のコンポーネントが正しく再描画します!だから私の質問は、コンポーネントの再レンダリングをトリガースライスの呼び出しですか?前と比べて、私はちょうどそれを普通に割り当てていました。

私がここで紛失していること/私が理解していないことはわかりませんか? "before"コードのコンソールログは、 "listsCopy"が期待どおりに変更されていることを示していたようでしたが、状態変更をトリガーしませんでした。

また、状態のコピーを使用していますが、それを変更していません。私はなぜスライスがここで違いを生むのか分かりません。

ありがとうございます!

答えて

0

あなたは配列を突然変異させています。 reduxでは、は常にに変更するものの新しいコピーを返す必要があります。

return {...state, lists: [...state.lists, action.item]}; 

スライスが動作し、プッシュしない理由は、.sliceが配列の新しいコピーを返すためです。プッシュ突然変異。

また、Object.assignの仕組みは...新しいルートオブジェクトを作成しますが、再帰的には機能しません。あなたのために何かを研究する:価値型と参照型の違い。値の型は、文字列、数値、ブール値、ヌル、または未定義のようなものです。これらの物はそれぞれ生の価値であり、直接比較することができます。ただし、参照型は、オブジェクトや配列、カスタムクラスや関数のインスタンスと似ています。本質的には、たとえ同じ内容であっても、直接比較することはできません。例えば

var foo = ['foo'] 
var bar = ['foo'] 
// foo === bar : false 

var a = Object.assign({}, {foo: foo}) 
// a.foo === foo : true 

var b = Object.assign({}, {foo: foo}, {foo: bar}) 
// b.foo === bar : true 
// b.foo === foo : false 

基本ルールは、あなたのメインの減速の内側(配列やオブジェクトなど)のネストされたオブジェクトを持っている任意の時間です - あなたはそれを変更した場合は、新しいコピーを返す必要があります。

reduxで起こっていることは、あなたがvar aの内部に見るものです。配列の内容を更新したにもかかわらず、reduxは、コンポーネントを更新する必要があるかどうかを判断するために、レデューサーの各ルートキーに対して厳密な等価チェックを実行しています。したがって、プッシュされた配列を返すと、そのオブジェクトは前の状態と同じであるとみなされます。これは、どちらの場合も配列の同じインスタンスであるためです。 Reduxは、配列(またはオブジェクト)の内部にあるものは考慮しません。

+0

これを追加するには、immutable.jsのようなライブラリを使用するのがreduxでうまく機能する理由があります。私の個人的な経験から、通常、オーバーヘッド(つまり定型文)と比較して、 –

関連する問題