如何在reducer中添加对象?

时间:2017-07-29 18:22:08

标签: javascript reactjs redux react-redux

我有一个看起来像这样的商店,数组中的3个对象带有数组。如何在携带索引1和2的第一个和第二个对象之间添加对象?

{
  object: [
    {
      "index": 1,
      "title": "title",
      "caption": "caption",
    },
    {
      "index": 2,
      "title": "title",
      "caption": "caption",
    },
    {
      "index": 3,
      "title": "title",
      "caption": "caption",
    },
  ]
}

在单击传递索引值为1的按钮后,希望得到这样的最终输出。

{
  object: [
    {
      "index": 1,
      "title": "title",
      "caption": "caption",
    },
    {
      "index": 2,
      "title": "NEW",
      "caption": "NEW",
    },
    {
      "index": 3,
      "title": "title",
      "caption": "caption",
    },
    {
      "index": 4,
      "title": "title",
      "caption": "caption",
    },
  ]
}

我可以使用以下代码通过操作更改索引值,但是如何在对象1和对象2之间添加另一个新对象,以及同时更改索引值?

switch (action.type) {
  case ADDCOMPONENT:
    return {
      ...state,
      object: state.object.map(component =>
          (component.index > action.index ?
          { ...component, index: component.index + 1 } : component)),
    };

5 个答案:

答案 0 :(得分:1)

import numpy as np
import pickle
x = np.random.randint(0, 2**63 - 1, dtype=np.int32)
d = {
    'x': x,
    'blah': "blah blah blah"
}
with open('bomb.pickle', 'wb+') as f:
    pickle.dump(d, f)

并且不要将项目索引保留为字符串。您可以轻松地获取数组中项目的位置,然后将值1添加到值

答案 1 :(得分:1)

state.object.splice(component.index, 0, component);

应该做的伎俩

答案 2 :(得分:1)

store的形状由所有减速器的组合创建。您要在商店中更新的数据应在应用程序中创建,然后通过dispatch(action)发送到您的reducer。 reducer获取action上的信息并相应更新您的状态。如果要将对象添加到数组中,可以使用Array.prototype.splice(),如下所示:myArray.splice( startIndex, 0, itemsToInsert, ... )

简而言之,请勿在减速器中添加对象。在发送操作之前,将其添加到您在操作中发送的数据中。

如果您希望能够将数据插入到数组中而不是改变它们,那么您应该考虑使用类似此代码段中的函数:

function nonMutatingArrayInsert( array, index, insert ) {
	// return array if index is outside range of array
        if ( index < 0 || index > array.length - 1 ) return array;  

        // ensure insert is array for concat purposes
        let _insert = Array.isArray( insert ) ? insert : [ insert ];

	// handle 0 index insert
	if ( index === 0 ) { return [ ..._insert, ...array ]; }

	// handle end of array insert
	if ( index === array.length ) { return [ ...array, ..._insert ] }

	// handle everyhing else
	const before = array.slice( 0, index );
	const after = array.slice( index, array.length );

	// return new non-mutated array
	return [ ...before, ..._insert, ...after ];
}

let myArray = [ "one", "four" ];

let newArray = nonMutatingArrayInsert( myArray, 1, ["two", "three"] );

console.log( "myArray:\n", myArray );
console.log( "newArray:\n", newArray );

答案 3 :(得分:1)

其他答案似乎忽略了您需要增加数组中其他对象的索引。我将分两步进行处理:首先使用splice添加新对象,然后循环并递增所有后续索引。

var index = 1;
state.object.splice(index, 0, new_component); //Insert the new object

//Starting where you inserted, add one to all later components
for (var i = index +1; i < state.object.length; i++) {
    state.object[i].index ++;
}

state保留您想要的值。

但是,我建议您考虑对象是否真的需要知道它们在数组中的位置。根据我的经验,任何需要访问对象的代码都能够告诉他们在数组中的位置。

答案 4 :(得分:0)

所有答案都有效,但为了不改变数组,我使用了以下代码。

先切割数组,然后在中间插入新对象。

  let newObject = state.portfolio.components.slice(0, action.index);
  newObject = newObject.concat(NEWOBJECT);
  newObject = newObject.concat(state.portfolio.components.slice(action.index));

  for (let i = action.index; i < newComponent.length; i++) {
    newComponent[i].index = i + 1;
  }

用newObject替换对象。

  switch (action.type) {
    case ADDCOMPONENT:
      return {
        ...state,
        object: newObject,
      };

EDITED:最终使用了不变性辅助函数,代码更简单,没有变异。

  return update(state, {
    portfolio: {
      object: {
        $splice: [
          [action.index + 1, 0, action.newObject],
        ],
      },
    }
  });