And*_*gan 6 javascript architecture flux reactjs redux
问题:
在大型React/Redux应用程序中组织容器,组件,操作和减速器的最可维护和建议的最佳实践是 什么?
我的看法:
目前的趋势似乎是围绕相关的容器组件组织redux抵押品(行动,减少器,传奇......).例如
/src
/components
/...
/contianers
/BookList
actions.js
constants.js
reducer.js
selectors.js
sagas.js
index.js
/BookSingle
actions.js
constants.js
reducer.js
selectors.js
sagas.js
index.js
app.js
routes.js
Run Code Online (Sandbox Code Playgroud)
这很棒!虽然这种设计似乎存在一些问题.
问题:
当我们需要访问时actions
,selectors
或者sagas
从另一个容器访问时,它似乎是一种反模式.假设我们有一个/App
带有reducer/state 的全局容器,它存储我们在整个应用程序中使用的信息,例如类别和枚举.继上面的例子之后,使用状态树:
{
app: {
taxonomies: {
genres: [genre, genre, genre],
year: [year, year, year],
subject: [subject,subject,subject],
}
}
books: {
entities: {
books: [book, book, book, book],
chapters: [chapter, chapter, chapter],
authors: [author,author,author],
}
},
book: {
entities: {
book: book,
chapters: [chapter, chapter, chapter],
author: author,
}
},
}
Run Code Online (Sandbox Code Playgroud)
如果我们想selector
在/App
容器中使用/BookList
容器,我们需要重新创建它/BookList/selectors.js
(肯定是错误的?)或者从中导入它/App/selectors
(它总是与EXACT相同的选择器吗??不.).这些appraoches对我来说似乎都不是最理想的.
这个用例的主要例子是身份验证(啊...我们确实喜欢讨厌你,因为它是一个非常常见的"副作用"模型).我们经常需要/Auth
在整个应用程序中访问传奇,动作和选择器.我们可能有集装箱/PasswordRecover
,/PasswordReset
,/Login
,/Signup
....其实在我们的应用程序我们/Auth
contianer没有实际分量可言!
/src
/contianers
/Auth
actions.js
constants.js
reducer.js
selectors.js
sagas.js
Run Code Online (Sandbox Code Playgroud)
简单地包含上面提到的各种且通常不相关的auth容器的所有Redux附属品.
我个人使用ducks-modular-redux提议.
这不是"官方"推荐的方式,但对我来说效果很好.每一个"鸭"包含actionTypes.js
,actionCreators.js
,reducers.js
,sagas.js
和selectors.js
文件.这些文件中没有依赖于其他鸭子以避免循环依赖或鸭圈,每个"鸭子"只包含它必须管理的逻辑.
然后,在根目录我有一个components
和一个containers
文件夹和一些根文件:
components/
文件夹包含我的应用程序的所有纯组件
containers/
文件夹包含从上面的纯组件创建的容器 当一个容器需要一个selector
涉及许多"ducks" 的特定容器时,我将它写在我编写该<Container/>
组件的同一个文件中,因为它与该特定容器相关.如果selector
共享accros多个容器,我在一个单独的文件(或提供这些道具的HoC)中创建它.
rootReducers.js
:通过组合所有reducer来简单地公开root reducer
rootSelectors.js
公开每个状态切片的根选择器,例如在您的情况下,您可能具有以下内容:
/* let's consider this state shape
state = {
books: {
items: { // id ordered book items
...
}
},
taxonomies: {
items: { // id ordered taxonomy items
...
}
}
}
*/
export const getBooksRoot = (state) => state.books
export const getTaxonomiesRoot = (state) => state.taxonomies
Run Code Online (Sandbox Code Playgroud)
它让我们"隐藏"每个ducks selectors.js
文件中的状态形状.由于每个都selector
在你的鸭子里面接收整个状态,你只需要导入文件中的相应rootSelector
内容selector.js
.
rootSagas.js
组成你鸭子里面的所有传奇,并管理涉及许多"鸭子"的复杂流动.
所以在你的情况下,结构可能是:
components/
containers/
ducks/
Books/
actionTypes.js
actionCreators.js
reducers.js
selectors.js
sagas.js
Taxonomies/
actionTypes.js
actionCreators.js
reducers.js
selectors.js
sagas.js
rootSelectors.js
rootReducers.js
rootSagas.js
Run Code Online (Sandbox Code Playgroud)
当我的"鸭子"足够小,我经常跳过的文件夹创建并直接写入一个ducks/Books.js
或一个ducks/Taxonomies.js
文件,所有这5个文件(actionTypes.js
,actionCreators.js
,reducers.js
,selectors.js
,sagas.js
)合并在一起.