Làm cách nào để thêm một phần tử vào mảng trong bộ giảm tốc của redux gốc React?


140

Làm cách nào để thêm các phần tử trong mảng arr[]trạng thái redux của tôi vào bộ giảm tốc? Tôi đang làm việc này-

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

Câu trả lời:


362

Hai tùy chọn khác nhau để thêm mục vào một mảng mà không bị đột biến

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

HOẶC LÀ

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

1
Cái nào nên được coi là thích hợp hơn?
sapht

19
@sapht nếu bạn đang viết mã trong ES6 thì mã đầu tiên thích IMO thanh lịch và dễ đọc hơn.
Yadhu Kiran

5
Ngoài ra, cái đầu tiên là thuần túy, cái thứ hai thì không. Từ các tài liệu Redux: "Điều rất quan trọng là bộ giảm tốc vẫn thuần túy. Những điều bạn không bao giờ nên làm trong bộ giảm tốc: 1. Biến đổi các đối số của nó; 2. Thực hiện các hiệu ứng phụ như các lệnh gọi API và chuyển tiếp định tuyến; 3. Gọi các hàm không thuần túy, ví dụ: Date.now () hoặc Math.random (). "
Robot quyến rũ

Xin chào, @YadhuKiran bạn có thể giải thích cho tôi lý do tại sao chúng tôi thêm giá trị mới trong chỉ mục thứ hai của mảng mà tôi không thể hiểu rõ về nó không? arr: [...state.arr, why here?]
Oliver D

@OliverD, Khi sử dụng cú pháp lây lan như trên, nó không chèn phần tử vào chỉ mục thứ hai, mà ở chỉ mục cuối cùng. Ngược lại với điều này, [action.newItem, ...state.arr]sẽ chèn phần tử ở vị trí đầu tiên.
Yadhu Kiran

22

pushkhông trả về mảng, nhưng độ dài của nó ( docs ), vì vậy những gì bạn đang làm là thay thế mảng bằng độ dài của nó, làm mất tham chiếu duy nhất đến nó mà bạn có. Thử cái này:

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
Bất cứ ai có thể trả lời câu hỏi này với Object.assignnhững thay đổi của mảng bên trong tiểu bang không?
Vennesa

2
Tại sao bạn cần Object.assign? Nó được sử dụng cho các đối tượng, và về cơ bản là giống nhau. Nơi bạn có arr:[...state.arr, action.newItem]bạn có thể sử dụng obj: Object.assign({}, state.obj, action.newItem, miễn là objnewItemlà đối tượng. Nếu bạn muốn làm điều đó với toàn bộ tiểu bang, bạn chỉ có thể làmObject.assign({}, state, {arr: [..state.arr, action.newItem]})
martinarroyo 17/03/18

1
@martinarroyo, cảm ơn vì vậy tôi đã làm: var obj = { isLoading: true, data: ['a', 'b', 'c', 'd'] } var newObj = Object.assign({}, obj, { data: [...obj.data, 'e'] });và nó mang lại cho tôi điều này: { isLoading: true, data: [ 'a', 'b', 'c', 'd', 'e' ] }cho newObj đủ tốt cho những gì tôi cần. Nhưng tôi muốn sử dụng Object.assign mà không có toán tử trải rộng để tạo ra kết quả tương tự. Điều đó có thể không?
Vennesa

1
@Vennesa Tôi đoán rằng bạn có thể thay thế nó bằng [].concat(obj.data, ['e']), nếu bạn không muốn sử dụng các tính năng ES6. Object.assign có nghĩa là cho các đối tượng và mặc dù nó sẽ không cung cấp cho bạn bất kỳ lỗi nào khi sử dụng nó trên một mảng, kết quả không phải là sự kết hợp của các mảng. Nếu bạn cố gắng Object.assign({}, [1, 2, 3], [4]), bạn sẽ có [4, 2, 3]kết quả.
martinarroyo

13

Nếu bạn cần chèn vào một vị trí cụ thể trong mảng, bạn có thể làm điều này:

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

Tôi vấp ngã ở đây ... mặc dù câu trả lời này không chính xác phù hợp với câu hỏi ở trên. Tuy nhiên, đó chính xác là những gì tôi đang tìm kiếm. Tôi đang tìm cách để chèn một đối tượng vào một chỉ mục cụ thể trong một mảng. Do đó, tôi đã bỏ phiếu trả lời. Nó rất hữu ích và giúp tôi tiết kiệm thời gian. Cảm ơn!
omostan

0

Tôi có một mẫu

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
thêm một số mô tả
SPatel
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.