如何将初始状态传递给reducer

时间:2017-07-17 00:27:09

标签: reactjs redux graphql

我目前使用一个减速器创建我的商店,该减速器已经传递了初始状态。

import reducers from './reducers'

const store = createStore(
    reducers,
    initialState,
    compose(...enhancers)
  )


// reducers.js
export default function reducer(state, action) {
  console.log('state', state)
  switch (action.type) {
    case 'LOAD_UI':
      return Object.assign({}, state, {
        loadUI: action.loaded
      });
    case 'NO_MATCH':
      return Object.assign({}, state, {
        loadUI: true,
        isNoMatch: action.isNoMatch
      });
    default:
      return state;
  }
}

当我在reducer函数中记录状态时,我得到了配置我的商店时设置的状态:

// if we are in production mode, we get the initial state from the window object, otherwise, when we are in dev env we get it from a static file
const preloadedState = window.__INITIAL_STATE__ === '{{__PRELOADEDSTATE__}}' ? initialState : window.__INITIAL_STATE__

const store = configureStore(preloadedState)

ReactDOM.render(
  <Provider store={store}>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </Provider>
, document.getElementById('root')
)

现在我想使用另一个reducer,因为我试图在我的项目中包含Apollo。根据{{​​3}},我需要结合使用减少器:即

combineReducers({
    todos: todoReducer,
    users: userReducer,
    apollo: client.reducer(),
  }),

所以我需要做这样的事情:

const store = createStore(
    combineReducers({
      apollo: client.reducer(),
      reducer: reducers
    }),
    initialState,
    compose(...enhancers)
  )

但是我的reducer函数不再具有访问状态的权限(它是未定义的)。当我使用combineReducers时,如何确保传递?

解决方案:

根据Daniel Rearden的建议,我需要将减速器的钥匙与我的初始状态相匹配。

我的initialState看起来像:

{
  "pages": [
    {
      "id": 5,
      "title": "About",
      "slug": "about",
      "path": "/about",
      "template": "about",
      "published": "2017-07-10 02:02:30",
      "image": null,
      "seo": {
        "title": null,
        "description": null,
        "image": null,
        "fbAdmins": null,
        "gtm": null,
        "schema": ""
      },
      "sections": [
      ]
    },
    {
      "id": 10,
      "title": "Contact",
      "slug": "contact",
      "path": "/contact",
      "template": "contact",
      "published": "2017-07-11 04:27:30",
      "image": null,
      "seo": {
        "title": null,
        "description": null,
        "image": null,
        "fbAdmins": null,
        "gtm": null,
        "schema": ""
      },
      "sections": []
    },
    {
      "id": 4,
      "title": "Home",
      "slug": "home",
      "path": "/",
      "template": "home",
      "published": "2017-07-10 01:39:48",
      "image": null,
      "seo": {
        "title": null,
        "description": null,
        "image": null,
        "fbAdmins": null,
        "gtm": null,
        "schema": ""
      },
      "sections": []
    }
  ],
  "services": [],
  "clients": [],
  "people": [],
  "offices": [],
  "articles": [],
  "menus": {
    "header": [
      {
        "title": "Home",
        "slug": "/"
      },
      {
        "title": "About",
        "slug": "/about"
      },
      {
        "title": "Contact",
        "slug": "/contact"
      }
    ]
  },
  "settings": {
    "site": {
      "title": null,
      "siteUrl": ""
    },
    "logo": [],
    "secondarylogo": [],
    "favicon": [],
    "disclaimer": null,
    "tagline": null,
    "social": null,
    "email": null,
    "phone": null,
    "facebookAppId": "",
    "seo": {
      "title": null,
      "description": null,
      "image": null,
      "fbAdmins": null,
      "gtm": null,
      "schema": ""
    },
    "newsLetterSignUp": {
      "image": "",
      "title": "",
      "content": ""
    },
    "menu_settings": null
  }
}

所以我的减速机看起来像这样:

import { combineReducers } from 'redux'
import { ApolloClient } from 'react-apollo';

const client = new ApolloClient();

import articles from './articles'
import pages from './pages'
import services from './services'
import clients from './clients'
import people from './people'
import offices from './offices'
import menus from './menus'
import settings from './settings'

export default combineReducers({
  apollo: client.reducer(),
  articles,
  pages,
  services,
  clients,
  people,
  offices,
  menus,
  settings
})

这样我的pages reducer只获取了我的initialState的页面切片。

1 个答案:

答案 0 :(得分:3)

之所以没有按照您的预期工作,是因为您改变了州的结构,以及传递给原始缩减器的内容。在您的商店看起来像这样的地方之前:

{
 loadUI: true
 isNoMatch: false
}

现在,你基本上告诉Redux寻找:

{
 apollo: {
   // ✁
 }
 reducers: {
   loadUI: true
   isNoMatch: false
 }
}

当你使用combineReducers时,你实际上是为你的状态创建了孤立的域 - 而不是将整个状态传递给每个reducer,redux只会将状态的一部分传递给每个reducer,而reducer只能通过改变那片状态。通过如上所示构建您的商店,您已经告诉redux只将状态的apollo切片传递给apollo reducer ...并将状态的reducers部分传递给原始的reducer。 / p>

我猜你没有对preloadedState做任何改动。所以正在发生的事情是,redux正在寻找preloadedState中名为reducers的属性,并将其传递给您的Reducer。它找不到一个,所以它传递未定义。

这里最简单的解决方法是首先选择比reducers更具描述性的内容 - ui?相应地更改combineReducers。然后更新您的preloadedState,以便您拥有的任何初始状态都嵌套在ui中。然后它应该按预期工作。请记住,您还需要更新选择器和/或mapStateToProps函数!

修改:您可能希望详细了解combineReducers的工作原理here