Соответствующее состояние Redux состоит из массива объектов, представляющих слои.

< EM> Пример:

let state = [
    { id: 1 }, { id: 2 }, { id: 3 }
]

У меня есть действие Redux под названием moveLayerIndex:

< Сильный > actions.js

export const moveLayerIndex = (id, destinationIndex) => ({
    type: MOVE_LAYER_INDEX,
    id,
    destinationIndex
})

Я бы хотел, чтобы редуктор обрабатывал действие, меняя положение элементов в массиве.

< Сильный > редукторы / layers.js

const layers = (state=[], action) => {
    switch(action.type) {
        case 'MOVE_LAYER_INDEX':

/ * Что я должен поставить здесь, чтобы пройти тестовый проход ниже * /

        default:
         return state
    }
}

Тест проверяет, что редуктор Redux меняет местами элементы массива неизменным образом.

Глубокая заморозка используется для проверки того, что исходное состояние не изменено каким-либо образом.

Как мне пройти этот тест?

< Сильный > тест / редукторы / index.js

import { expect } from 'chai'
import deepFreeze from'deep-freeze'

const id=1
const destinationIndex=1

 it('move position of layer', () => {
    const action = actions.moveLayerIndex(id, destinationIndex)
    const initialState = [
        {
          id: 1
        },
        {
          id: 2
        },
        {
          id: 3
        }
    ]
    const expectedState = [
        {
          id: 2
        },
        {
          id: 1
        },
        {
          id: 3
        }
    ]
    deepFreeze(initialState)
    expect(layers(initialState, action)).to.eql(expectedState)
 })
7
therewillbecode 13 Дек 2016 в 20:52

3 ответа

Лучший ответ

Одна из ключевых идей неизменяемых обновлений заключается в том, что, хотя вы никогда не должны напрямую изменять исходные элементы, можно сделать копию и изменить ее перед возвратом .

Имея это в виду, эта функция должна делать то, что вы хотите:

function immutablySwapItems(items, firstIndex, secondIndex) {
    // Constant reference - we can still modify the array itself
    const results= items.slice();
    const firstItem = items[firstIndex];
    results[firstIndex] = items[secondIndex];
    results[secondIndex] = firstItem;

    return results;
}

Я написал раздел для документов Redux под названием Структурирующие редукторы - шаблоны неизменных обновлений который дает примеры некоторых связанных способов обновления данных.

8
markerikson 28 Мар 2017 в 23:30

Вы можете использовать функцию map , чтобы сделать обмен:

function immutablySwapItems(items, firstIndex, secondIndex) {
    return items.map(function(element, index) {
        if (index === firstIndex) return items[secondIndex];
        else if (index === secondIndex) return items[firstIndex];
        else return element;
    }
}

В стиле ES2015:

const immutablySwapItems = (items, firstIndex, secondIndex) =>
  items.map(
    (element, index) =>
      index === firstIndex
        ? items[secondIndex]
        : index === secondIndex
        ? items[firstIndex]
        : element
  )
4
Geraldo B. Landre 20 Апр 2017 в 03:48

В двух других ответах нет ничего плохого, но я думаю, что есть еще более простой способ сделать это с ES6.

const state = [{
  id: 1
}, {
  id: 2
}, {
  id: 3
}];

const immutableSwap = (items, firstIndex, secondIndex) => {
  const result = [...items];
  [result[firstIndex], result[secondIndex]] = [result[secondIndex], result[firstIndex]];
  return result;

}

const swapped = immutableSwap(state, 2, 0);

console.log("Swapped:", swapped);
console.log("Original:", state);
0
Prateek Surana 17 Мар 2020 в 09:48