2017-03-02 69 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