如何在react-redux中正确更新我的initialState

时间:2017-01-20 07:41:24

标签: javascript reactjs ecmascript-6 redux react-redux

我有一个initialState:

export default {
  dashboards: [],
  dashboardContent: []
};

我希望在执行此类操作后通过reducer更新:

import initialState from './initialState';
import * as types from '../actions/actionTypes';

export default function dashboardContentReducer(state = initialState, action) {
  switch(action.type) {
    case types.LOAD_DASHBOARD_CONTENT_SUCCESS:
      return Object.assign({}, state, { dashboardContent: action.dashboardContent });
    default:
      return state;
  }
}

import initialState from './initialState';
import * as types from '../actions/actionTypes';

export default function dashboardReducer(state = initialState, action) {
  switch(action.type) {
    case types.LOAD_DASHBOARDS_SUCCESS:
      return Object.assign({}, state, { dashboards: action.dashboards });
    default:
      return state;
  }
}

在调度动作后,当我查看我的商店时,我发现它已经更新,但是有一个级别太深了:

{
  dashboards: {
    dashboards: [/* array received from reducer */],
    dashboardContent: []
  },
  dashboardContent: {
    dashboards: [],
    dashboardContent: [/* array received from reducer */]
  }
}

如何使它变成我想要的,应该只是:

{
  dashboards: [/* payload received from reducer */],
  dashboardContent: [/* payload received from reducer */]
}

编辑:

以下是有效载荷的外观。

对于dashboardContent:

[
  {
    application: 'Company News',
    site: 'Home',
    lastUpdated: 'Jun 1, 2016 10:30',
    location: 'Asbury',
    views: 123451,
    individuals: 2345
  },
  {
    application: 'Company News',
    site: 'Home',
    lastUpdated: 'Jun 1, 2016 10:30',
    location: 'Asbury',
    views: 123451,
    individuals: 2345
  },
  {
    application: 'Company News',
    site: 'Home',
    lastUpdated: 'Jun 1, 2016 10:30',
    location: 'Asbury',
    views: 123451,
    individuals: 2345
  },
  {
    application: 'Company News',
    site: 'Home',
    lastUpdated: 'Jun 1, 2016 10:30',
    location: 'Asbury',
    views: 123451,
    individuals: 2345
  },
  {
    application: 'Company News',
    site: 'Home',
    lastUpdated: 'Jun 1, 2016 10:30',
    location: 'Asbury',
    views: 123451,
    individuals: 2345
  }
];
仪表板的

[
  {
    id: 1,
    title: "Overview",
    template: "main",
    category: "Main",
    sort: {},
    filter: {
    loginType: "All Accounts",
    Pivot: "location",
    pivotValue: 1
    },
    priority: 0,
    readonly: true
  },
  {
    id: 2,
    title: "Top Applications",
    template: "application-usage",
    category: "Application Usage",
    sort: {
      first: {
        by: "views",
        direction: "desc"
      },
      second:  {
        By:"individuals",
        direction: "desc"
      }
    },
    filter: {
      application: 0,
      Pivot: location,
      pivotValue: 1
    },
    priority: 1,
    readonly: true,
    createdDate: "2016-12-29T16:37:11.62Z",
    updatedDate: "2016-12-29T16:37:11.62Z"
  }
]

3 个答案:

答案 0 :(得分:2)

由于您使用的是两个不同的Reducer,并且您了解initialState,为什么不将reducers修改为

import initialState from './initialState';
import * as types from '../actions/actionTypes';

export default function dashboardContent(state = [], action) {
  switch(action.type) {
    case types.LOAD_DASHBOARD_CONTENT_SUCCESS:
      return Object.assign({}, state, action.data);
    default:
      return state;
  }
}

和另一个

import initialState from './initialState';
import * as types from '../actions/actionTypes';

export default function dashboard(state = [], action) {
  switch(action.type) {
    case types.LOAD_DASHBOARDS_SUCCESS:
      return Object.assign({}, state, action.data);
    default:
      return state;
  }
}

好吧,我已经更改了reducers的名称,但是在使用combineReducers时,命名无论如何都无关紧要。你可以随时做。

combineReducers({
  dashboardContent:dashboardContentReducersWhichHasBeenGivenAWeirdName,
  dashboard:dashboardReducerAgainNamedWeird
})

您的州将被创建为{dashboard:[],dashboardContent:[]}

通过这种方式,您可以避免错误级别的更新。 我还建议您查看explanation here by Dan,它会详细解释createStore如何根据您的reducer创建状态,以及intialState如何优先。

答案 1 :(得分:1)

来自combineReducers文档:

  

生成的减速器调用每个儿童减速器,然后收集它们   结果成一个状态对象。状态对象的形状   匹配传递的Redurs的键。

     

因此,状态对象将如下所示:

{
  reducer1: ...
  reducer2: ...
}

因此在使用它时,为了让两个reducers共享状态,你需要创建一个这样的reducer:

import initialState from './initialState';
import * as types from '../actions/actionTypes';

export default function dashboardReducer(state = initialState, action) {
  switch(action.type) {
    case types.LOAD_DASHBOARDS_SUCCESS:
      return Object.assign({}, state, { dashboards: action.dashboards });
    case types.LOAD_DASHBOARD_CONTENT_SUCCESS:
      return Object.assign({}, state, { dashboardContent: action.dashboardContent });
    default:
      return state;
  }
}

或者,如果您因任何原因想要将逻辑分开,可以使用reduce-reducers库:

import reduceReducers from "reduce-reducers";
import dashboardReducer from "./dashboardReducer";
import dashboardContentReducer from "./dashboardContentReducer";

const combined = reduceReducers(dashboardReducer, dashboardContentReducer);

createStore(combineReducers({ dashboard: combined }));

这样你就会有一个状态对象:

{
    dashboard: {
        dashboards: []
        dashboardContent: []
    }
}

答案 2 :(得分:0)

您需要定位内部dashboards而不是外部export default function dashboardReducer(state = initialState, action) { switch(action.type) { case types.LOAD_DASHBOARDS_SUCCESS: return Object.assign({}, state, { dashboards: Object.assign({},state.dashboards,{dashboards: action.dashboards} }); default: return state; } } 。尝试

export default function dashboardContentReducer(state = initialState, action) {
  switch(action.type) {
    case types.LOAD_DASHBOARD_CONTENT_SUCCESS:
      return Object.assign({}, state, { 
                dashboards: Object.assign({},state.dashboards,{dashboardContent: action.dashboardContent}
             });
    default:
      return state;
  }
}

<!doctype html>
<html>
<body>
    <p>You will be redirected in 3 seconds</p>
    <script>
        var time = setTimeout(function () {
            window.location = 'http://example.com'
        }, 3000);

        var one = setTimeout(function () {
            window.location = 'http://google.com'
        }, 6000);
    </script>
</body>
</html>