【问题标题】:Add object to nested array将对象添加到嵌套数组
【发布时间】:2019-07-17 13:06:49
【问题描述】:

我的初始状态为

sites = [

{id, name, vehicles[], drivers[]},
{id, name, vehicles[], drivers[]},
{id, name, vehicles[], drivers[]},
{id, name, vehicles[], drivers[]},

];

当从组件 SiteVehcleSelection 中的列表中选择车辆时,我正在尝试将车辆添加到给定站点,并且处理选择的方法是:

 handleVehicleSelection = (event) => {
    const vehicle = this.props.vehicles.find((v) => v.id === parseInt(event.target.dataset.id, 10));
    this.props.handleVehicleSelection(event, this.state.site.id, {...vehicle});
  };

将其传递给父 SiteList 方法:

  handleVehicleSelection = (event, siteId, vehicle) => {
    this.props.dispatch(siteActions.handleVehicleSelect(siteId, vehicle), event.target.checked);

}

从 SiteList 类调用:

export function handleVehicleSelect(siteId, vehicle, cmd){
  return (dispatch) => {
    debugger;
    return fetch(`${BASE_URL}/accounts/site-vehicle-action/${siteId}/${vehicle.id}/${cmd}`, {
      method: 'PUT',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: ''
    }).then((res) => {
      return res.json();
    }).then((json) => {
      if (json.msg === true) {
        dispatch(vehicleSelect(siteId, vehicle));
      }
    });
  }
}

发送到这个:

export function vehicleSelect(siteId, vehicle){
  return {type: actionTypes.ADD_VEHICLE_TO_SITE, siteId, vehicle};
}

我的减速器是:

 case actionTypes.ADD_VEHICLE_TO_SITE:
    debugger;
    const siteIndex = state.findIndex((site) => site.id === action.siteId);
    console.log(state);
     const newState = [...state.slice(0, siteIndex), {...state[siteIndex], vehicles: [...state[siteIndex].vehicles, action.vehicle],}, ...state.slice(siteIndex +1)];
     console.log(newState);
     return newState;

当我在更改发生之前和之后登录时,车辆已添加到正确的站点但它没有在视图中显示/刷新这里是之前和之后状态的记录。

更改前:

0: {drivers: Array(0), id: 1, name: "Site One", vehicles: Array(0)}
1: {drivers: Array(0), id: 2, name: "Site Two", vehicles: Array(0)}
2: {drivers: Array(0), id: 3, name: "Site Three", vehicles: Array(0)}
length: 3
__proto__: Array(0)

改动后:

0: {drivers: Array(0), id: 1, name: "Site One", vehicles: Array(1)}
1: {drivers: Array(0), id: 2, name: "Site Two", vehicles: Array(0)}
2: {drivers: Array(0), id: 3, name: "Site Three", vehicles: Array(0)}
length: 3
__proto__: Array(0)

可以看到第一个已正确添加车辆,这是新状态,但返回时没有任何反应,好像站点列表没有刷新一样。

希望这个编辑有助于解释更多。

【问题讨论】:

  • 你不能对你的状态做一个深拷贝,修改复制的状态并返回它吗?状态应该是不可变的。
  • 是否要将新对象添加到items1 数组中?据我所知,你没有这样做。您能否通过action 或至少action.site 提供您的初始状态和期望状态?
  • 是的,我想在 items1 数组中添加一个新对象。
  • 您能给我们举个具体的例子吗?您可以更新您的问题。只需提供初始/所需状态和您的操作即可。
  • 我仍然看不到具体的例子。初始/所需状态和您传递的操作对象。请为您的数据提供简单的示例。

标签: javascript reactjs ecmascript-6 redux


【解决方案1】:

我认为下面的代码会有所启发。我假设你有相应的索引。

let state = [
    { id: "id1", name: "name1", items: [{},{}] },
    { id: "id2", name: "name2", items: [{},{}] },
]

function reducer() {
    switch("Action") {
        case ADD_SITE: { // add new element to state
            return [
                ...state,
                payload.site,
            ]
        }

        case ADD_SITE_AT_INDEX: { // add new element to state at index: idx
            return [
                ...state.slice(0, idx),
                payload.newSite,
                ...state.slice(idx)
            ]
        }

        case ADD_ITEM: { // add new item to site with index: idx
            return [
                ...state.slice(0, idx),
                {
                    ...state[idx],
                    items: [
                        ...state[idx].items,
                        payload.newItem
                    ],
                },
                ...state.slice(idx+1)
            ]
        }

        case ADD_ITEM_AT_INDEX: { // add new item to site with index: idx, at item index: item_idx
            return [
                ...state.slice(0, idx),
                {
                    ...state[idx],
                    items: [
                        ...state[idx].items.slice(0, item_idx),
                        payload.newItem,
                        ...state[idx].items.slice(item_idx),
                    ],
                },
                ...state.slice(idx+1)
            ]
        }
    }
}

【讨论】:

  • 我尝试了 ADD_ITEM 部分,但我收到了这个错误 在调度中检测到状态突变,在路径中:sites.1。看一下处理动作 {"type":"ADD_VEHICLE_TO_SITE","siteId":1,"vehicle":{"cmets":"N/A","id":1,"make ":"Toyota","model":"Carina","re​​gistration":"20/1998"}}。 [...state.splice(0, siteIndex), {...state[siteIndex], 车辆: [...state[siteIndex].vehicles, action.vehicle],}, ...state.splice(siteIndex +1)];
  • 尝试使用切片而不是拼接,代码中也进行了更新
  • 我已经对 slice 进行了更改,正如您在我对问题的编辑中看到的那样,车辆似乎已添加到状态中,但似乎没有刷新对站点列表视图的更改.
  • 因此,使用上面的代码,您可以正确获取状态。为了进一步调试,您可以检查组件的 componentWillReceiveProps() 是否被触发。另外,在操作后检查 chrome 控制台中的最终状态。
  • 在 siteList compoenentWillReceiveProps() 函数中,如果我 console.log(nextProps) 到 chrome 控制台,结果是:0: {drivers: Array(0), id: 1, name: "Site One “,车辆:数组(1)} 1:{驱动程序:数组(0),id:2,名称:“站点二”,车辆:数组(0)} 2:{驱动程序:数组(0),id:3 , name: "Site Three", Vehicles: Array(0)} 其中车辆似乎添加好了,但不要在应用程序中刷新。
【解决方案2】:

假设这是你的状态结构与键(我给键随机命名,所以我可以解释)

{
  data:[{id:"some_id",name:"some_name",items1:[{},{}]}]
}
//suppose this is your reducer code.
case ADD_ITEM:
return{
 ...state,
 data: state.data.map(val=>{
   if(val.Id===action.payload.Id){
    return{
   ...val,
   items1:[...val.items1,action.payload.data]
   }
}
return{...val}
})
}

在这里,您将通过以下操作发送 Id 和数据:

{type:"ADD_ITEM",payload:{Id,data}}

其中 id 将是需要更新数组的第一级对象的 id, data 将是您要添加到数组中的数据..

【讨论】:

  • 嗨,我的初始状态是一个数组而不是一个对象。导出默认函数 siteReducer(state=[], action) 它会填充一个列表。
  • 我试过这个:return [...state, state.map(site => { if(site.id === action.site.id){ return { ...site, vehicle : [...site.vehicles, action.vehicle] } } return {...site} })];仍然会出现突变错误
  • 试试这个:return (state.map(site => { if(site.id === action.site.id){ return { ...site, vehicle: [...site .vehicles, action.vehicle] } } return {...site} }));
  • 调度中的相同问题突变。
【解决方案3】:

如果您只想将对象添加到具有给定结构的数组中,您可以这样做:

Structure
[
  { id, name, items1[{object},{object}]
]

复制现有状态,然后将新对象添加到数组末尾。

return {
  ...state,
  items1: state.items1.concat(action.newObject),
};

或使用 ES6 传播

return {
  ...state,
  items1: [...state.items1, action.newObject],
};
// state: { id, name, items1: [{object},{object},{newObject}] }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-12
    • 1970-01-01
    相关资源
    最近更新 更多