2017-03-02 72 views
0

我目前從Redux開始,並且我不清楚綁定Reducer到sub,動態設置狀態部分的正確方法。將reducer綁定到狀態的子集,動態設置

比如假設我的狀態看起來像這樣(後異步讀取從後端API的一些數據)

{ 
    "categories": { 
     "collection": { 
     "42": { 
      "id": "42", 
      "title": "whatever", 
      "owner_id": "10" 
      "posts": { 
       "collection": { 
       "36": { 
        "id": "36", 
        "title": "hello", 
        "content": "hello world" 
       }, 
       "37": { // more posts ... } 
       }, 
       "ids": ["36", "37", ...] 
      }, 
      "otherChildren": { // more sub-entities } 
     }, 
     "43": { // more categories ... } 
     }, 
     "ids": ["42", "43", ...] 
    }, 
    "users": { 
    "collection": { 
     "10": { 
      "id": "10" 
      "email": "[email protected]" 
     }, 
     "11": { // more users ... } 
    }, 
    "ids": [10, 11] 
    } 
} 

我的根減速應該是這樣的:

export default combineReducers({ 
    categories: categoriesReducer, 
    users: usersReducer 
}) 

和categoriesReducer:

function categoriesReducer(state = initialState, action) { 
    switch (action.type) { 
    case FETCH_ALL_CATEGORIES_SUCCESS: 
     return Object.assign({}, state, { 
     categories: { 
      collection: action.payload 
     } 
     }) 
    default: 
     return state 
    } 
} 

現在我想要做的是無縫委託處理與postsReducer功能的狀態的post子集部分,基本上增加的情況下,如:

case FETCH_CATEGORY_ALL_POSTS_SUCCESS: 
    let categoryId = action.categoryId 
    return Object.assign({}, state, { 
     categories: { 
     [categoryId]: combineReducers({ 
      "posts": postsReducer, 
      "otherChildren": otherChildrenReducer 
     }) 
     } 
    } 

當然,這是行不通的。我沒有得到的是如何讓redux自動更新使用combineReducer嵌套reducer的狀態的一個子集,同時自動將適當的子集作爲狀態參數傳遞給reducer函數,並且不會覆蓋現有的數據(即類別in我的例子)。

我以某種方式設法使這項工作寫我自己的「委託」功能,但它感覺非常錯誤 - 尤其是看看https://github.com/reactjs/redux/blob/master/src/combineReducers.js,看起來像這樣做。

傳統上,我怎麼會這麼做?那甚至有可能以Redux的方式使用combineReducers,我誤解了combineReducer的觀點,還是期待它有很多魔力?

謝謝!

編輯/ UPDATE:

我真的需要做那些被嵌套(右,也許category/post例子是不正確的),我想減速(即在這裏,postsReducer ,但它可能是一個Collection減速機)可以在多個地方重複使用。

爲什麼我希望它被嵌套?實際上,在這個例子中,讓我們說,一個post只能屬於一個category,因爲post數據實際上是用私鑰從category加密的。這就是爲什麼它對我來說代表這個鏈條,這種關係在狀態非常敏感)

是否有一種方式與redux委託給其他reducer同時傳遞狀態的正確的子集 - 例如,通過狀態categories.collection.42.posts.collection.36到postReducer?

+0

爲什麼它的價值,什麼都不會「自動」更新。減速器只是**功能。您可能想閱讀http://redux.js.org/docs/recipes/StructuringReducers.html以獲得一些想法。 – markerikson

+0

如果您想要爲不同的數據實體具有相似或完全相似的縮減器,請參閱編寫reducer生成器:http://redux.js.org/docs/recipes/ReducingBoilerplate.html#generating-reducers,也在這裏:http ://redux.js.org/docs/recipes/reducers/ReusingReducerLogic.html。你可以進行授權,但只能在一個方向上(從不那麼特定到更具體)。最終的結果是一個減速器樹。但是你所說的聽起來像是循環式的代表團。 – NateQ

+0

如果你真的想在商店中嵌套另一種類型的數據實體,當然你可以自由地這樣做,只要你以樹形式實現減速器。正如上面的提示,我還建議你回去閱讀http://redux.js.org上的文檔,它們寫得很好,很有幫助。 – NateQ

回答

0

你在哪裏和店面做得很好,爲什麼不分開所有不同的收藏。

我的意思是你的職位應/可以有另一種減速器,商店將連接起來是這樣的:

{ 
    categories: [], 
    posts: [], 
    users: [] 
} 

那麼您的類別將只包含帖子的ID的

,所以你可以「捕捉「在兩個還原器(類別和新職位reducer)中的」FETCH_ALL_CATEGORIES_SUCCESS「操作,categoryReducer的安全類別數據以及ID和postsReducer將只保存帖子

+0

謝謝@Borjante。我用更多的細節更新了這個問題,參見上文! – nakwa

0

您正在以錯誤的方式使用combineReducers在最後的代碼片段中。 (在第一個片段中,您正在使用它來將categoriesReducer和usersReducer組合在一起。)

在FETCH_CATEGORY_ALL_POSTS_SUCCESS的情況下,而不是調用combineReducers,只需在categoriesReducer中調用普通函數即可。

posts: posts(action.payload.posts) 

這個普通函數基本上是一個子簡化器。這會是你自己寫的,你可能會把它放在同一個文件中。

但其他兩個以上的代碼主要問題:

1)由於其他用戶已經上面所說的,它可能不會是最好的存儲員額類別的子屬性。而是將帖子作爲自己的項目存儲在狀態樹中,並且每個帖子都有一個category_id字段來顯示它屬於哪個類別。因此,在這種情況下,你的狀態樹看起來像:

{ 
    categories: {}, 
    posts: {}, 
    users: {} 
} 

,你將首先使用combineReducers爲:

export default combineReducers({ 
    categories: categoriesReducer, 
    posts: postsReducer, 
    users: usersReducer 
}) 

2)在categoriesReducer(或任何爲此事),你不必須具有categories屬性,因爲您在致電combineReducers時已創建該屬性。換句話說,在categoriesReducer你應該只是這樣:

function categoriesReducer(state = initialState, action) { 
    switch (action.type) { 
    case FETCH_ALL_CATEGORIES_SUCCESS: 
     return Object.assign({}, state, { 
     collection: action.payload, 
     ids: // function to extract ids goes here 
     }); 
    default: 
     return state; 
    } 
} 
+0

謝謝@NateQ。我用更多的細節更新了這個問題,參見上文! – nakwa