Reactネイティブreduxのレデューサーで配列に要素を追加するにはどうすればよいですか?


140

arr[]レデューサーのredux状態の配列に要素を追加するにはどうすればよいですか?私はこれをやっています-

import {ADD_ITEM} from '../Actions/UserActions'
const initialUserState = {
    arr:[]
}

export default function userState(state = initialUserState, action)
{
    console.log(arr);
    switch (action.type)
    {
        case ADD_ITEM: 
            return { 
                      ...state,
                      arr: state.arr.push([action.newItem])
                   }

        default:
            return state
    }
}

回答:


363

変更なしで配列に項目を追加する2つの異なるオプション

case ADD_ITEM :
    return { 
        ...state,
        arr: [...state.arr, action.newItem]
    }

または

case ADD_ITEM :
    return { 
        ...state,
        arr: state.arr.concat(action.newItem)
    }

1
どちらが望ましいと考えるべきですか?
サフト

19
@sapht ES6でコードを記述している場合は、最初のコードがより読みやすくエレガントなIMOを優先します。
Yadhu Kiran

5
また、1つ目は純粋ですが、2つ目は純粋ではありません。Reduxのドキュメントから:「レデューサーを純粋な状態に保つことは非常に重要です。レデューサー内で絶対にすべきではないこと:1.引数を変更する; 2. API呼び出しやルーティング遷移などの副作用を実行する; 3.非純粋な関数を呼び出す、例:Date.now()またはMath.random()。 "
チャーミングロボット

こんにちは、@ YadhuKiranは、配列の2番目のインデックスに新しい値を追加する理由を私に説明できますか?arr: [...state.arr, why here?]
Oliver D

@ OliverD、spread構文が上記のように使用されている場合、要素は2番目のインデックスではなく、最後のインデックスに挿入されます。これとは対照的に[action.newItem, ...state.arr]、最初の位置に要素を挿入します。
Yadhu Kiran

22

pushは配列を返しませんが、配列の長さ(docs)を返します。そのため、あなたがしていることは、配列をその長さに置き換えて、持っていた唯一の参照を失うことです。これを試して:

import {ADD_ITEM} from '../Actions/UserActions'
const initialUserState = {

    arr:[]
}

export default function userState(state = initialUserState, action){
     console.log(arr);
     switch (action.type){
        case ADD_ITEM :
          return { 
             ...state,
             arr:[...state.arr, action.newItem]
        }

        default:return state
     }
}

1
誰でもこの質問に答えることができますObject.assignか?
Vennesa 2018年

2
なぜ必要なのObject.assignですか?オブジェクトに使用されますが、基本的には同じです。あなたが持っている場所は、それがオブジェクトである限り、をarr:[...state.arr, action.newItem]使用できます。それを州全体にしたい場合は、次のようにしてくださいobj: Object.assign({}, state.obj, action.newItemobjnewItemObject.assign({}, state, {arr: [..state.arr, action.newItem]})
martinarroyo

1
@martinarroyo、ありがとう、私はそうしました:var obj = { isLoading: true, data: ['a', 'b', 'c', 'd'] } var newObj = Object.assign({}, obj, { data: [...obj.data, 'e'] });そしてそれは私にこれを与えます:{ isLoading: true, data: [ 'a', 'b', 'c', 'd', 'e' ] }私が必要とするものに十分なnewObjのため。しかし、spreadオペレーターなしでObject.assignを使用して同じ結果を生成したかったのです。それは可能ですか?
Vennesa 2018年

1
@Vennesa [].concat(obj.data, ['e'])ES6の機能を使いたくない場合は、に置き換えることができると思います。Object.assignはオブジェクト用であり、配列で使用してもエラーは発生しませんが、結果は配列の連結ではありません。しようObject.assign({}, [1, 2, 3], [4])とする[4, 2, 3]と、結果として得られます。
martinarroyo

13

配列の特定の位置に挿入する必要がある場合、これを行うことができます:

case ADD_ITEM :
    return { 
        ...state,
        arr: [
            ...state.arr.slice(0, action.pos),
            action.newItem,
            ...state.arr.slice(action.pos),
        ],
    }

私はここでつまずきました...この答えは上記の質問に完全には一致しませんが。それにもかかわらず、それはまさに私が探していたものでした。配列の特定のインデックスにオブジェクトを挿入する方法を探していました。したがって、私は答えを投票しました。これは非常に役に立ち、時間を節約できました。ありがとう!
オモスタン

0

サンプルがあります

import * as types from '../../helpers/ActionTypes';

var initialState = {
  changedValues: {}
};
const quickEdit = (state = initialState, action) => {

  switch (action.type) {

    case types.PRODUCT_QUICKEDIT:
      {
        const item = action.item;
        const changedValues = {
          ...state.changedValues,
          [item.id]: item,
        };

        return {
          ...state,
          loading: true,
          changedValues: changedValues,
        };
      }
    default:
      {
        return state;
      }
  }
};

export default quickEdit;

1
説明を追加
SPatel
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.