2016-04-22 85 views
26

是否可以被嵌套結構如下減速器結合:嵌套終極版減速器

import 'user' from ... 
import 'organisation' from ... 
import 'auth' from ... 
// ... 

export default combineReducers({ 
    auth: { 
    combineReducers({ 
     user, 
     organisation, 
    }), 
    auth, 
    }, 
    posts, 
    pages, 
    widgets, 
    // .. more state here 
}); 

凡國家有結構:

{ 
    auth: { 
     user: { 
      firstName: 'Foo', 
      lastName: 'bar', 
     } 
     organisation: { 
      name: 'Foo Bar Co.' 
      phone: '1800-123-123', 
     }, 
     token: 123123123, 
     cypher: '256', 
     someKey: 123, 
    } 
} 

auth減速機具有結構:

{ 
    token: 123123123, 
    cypher: '256', 
    someKey: 123, 
} 

所以也許擴散算子是方便的? ...auth不知道:-(

回答

37

這是完全正常的使用combineReducers您嵌套減速器結合但還有另一種模式是非常方便的:。嵌套減速器

const initialState = { 
    user: null, 
    organisation: null, 
    token: null, 
    cypher: null, 
    someKey: null, 
} 

function authReducer(state = initialState, action) { 
    switch (action.type) { 
    case SET_ORGANISATION: 
     return {...state, organisation: organisationReducer(state.organisation, action)} 

    case SET_USER: 
     return {...state, user: userReducer(state.user, action)} 

    case SET_TOKEN: 
     return {...state, token: action.token} 

    default: 
     return state 
    } 
} 

在上面的例子中,authReducer能將動作轉發到organisationReduceruserReducer以更新其狀態的某些部分

+0

whoa ..好吧,這很好。雖然這是否意味着我的狀態樹中有'organisation'和'user'的多個副本? – AndrewMcLagan

+1

是的,你絕對應該這個項目:https://github.com/mweststrate/redux-todomvc。這是使用這些技巧的todomvc的優化版本。 – Florent

+0

我喜歡這個想法,儘管它似乎使應該很簡單的事情變得複雜。 :-( – AndrewMcLagan

21

只是想詳細闡述一下非常好的答案@Florent給出並指出,您還可以構建您的應用程序,實現嵌套的縮減器, 有了根減速器從減速器,其也結合減速器

例如

// src/reducers/index.js 
import { combineReducers } from "redux"; 
import auth from "./auth"; 
import posts from "./posts"; 
import pages from "./pages"; 
import widgets from "./widgets"; 

export default combineReducers({ 
    auth, 
    posts, 
    pages, 
    widgets 
}); 

// src/reducers/auth/index.js 
// note src/reducers/auth is instead a directory 
import { combineReducers } from "redux"; 
import organization from "./organization"; 
import user from "./user"; 
import security from "./security"; 

export default combineReducers({ 
    user, 
    organization, 
    security 
}); 

這假定一個位的狀態結構的不同組合。相反,像這樣:

{ 
    auth: { 
     user: { 
      firstName: 'Foo', 
      lastName: 'bar', 
     } 
     organisation: { 
      name: 'Foo Bar Co.' 
      phone: '1800-123-123', 
     }, 
     security: { 
      token: 123123123, 
      cypher: '256', 
      someKey: 123 
     } 
    }, 
    ... 
} 

@弗洛朗的做法可能會更好,如果你無法改變國家的結構,但是

+0

不錯的一個,不知道爲什麼我認爲這是不可能的:O –

+0

隨着你的狀態增長,這個解決方案似乎更容易維護。 –

+0

@JosephNields這是否意味着只要組件的prop連接到允許說'用戶'狀態並且另一個組件的prop連接可以對'auth'狀態說​​,那麼這兩個組件都會在它們的狀態改變時被重新渲染?這不是重複的渲染?換句話說,如果我們有一個'Auth'組件,它可以讓'User'組件構成,並且每當'User'中的狀態改變支持時,根據您的建議'Auth'和'User'會重新渲染,對嗎? – user3764893

1

通過@啓發florent's的答案,我發現你也可以試試這個。不一定比他的回答好,但我認爲它更優雅。

function userReducer(state={}, action) { 
    switch (action.type) { 
    case SET_USERNAME: 
     return state.name = action.name; 
    default: 
     return state 
    } 
} 

function authReducer(state = { 
    token: null, 
    cypher: null, 
    someKey: null, 
}, action) { 
    switch (action.type) { 
    case SET_TOKEN: 
     return {...state, token: action.token} 
    default: 
     // note: since state doesn't have "user", 
     // so it will return undefined when you access it. 
     // this will allow you to use default value from actually reducer. 
     return {...state, user: userReducer(state.user, action)} 
    } 
}