问题:
What is the most maintainable and recommended best practice for organising containers, components, actions and reducers in a large React/Redux application?
我的看法:
当前的趋势似乎是围绕相关的容器组件来组织 redux 抵押品(actions、reducers、sagas...)。例如
/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
这很好用!尽管此设计似乎存在一些问题。
问题:
当我们需要从另一个容器访问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,
}
},
}
如果我们想在 /BookList 容器中使用 /App 容器中的 selector,我们需要在 中重新创建它>/BookList/selectors.js(肯定是错的?)或者从 /App/selectors 导入它(它总是完全相同的选择器吗?不。)。这两种方法对我来说都不是最佳选择。
此用例的主要示例是身份验证(啊...我们确实爱恨你的身份验证),因为它是非常常见的“副作用”模型。我们经常需要在整个应用程序中访问 /Auth sagas、操作和选择器。我们可能有容器 /PasswordRecover, /PasswordReset, /Login, /Signup .... 实际上在我们的应用程序 /Auth contianer 根本没有实际组件!
/src
/contianers
/Auth
actions.js
constants.js
reducer.js
selectors.js
sagas.js
简单地包含上面提到的各种通常不相关的身份验证容器的所有 Redux 附带 Material 。
最佳答案
我个人使用 ducks-modular-redux提案。
这不是“官方”推荐的方式,但对我来说效果很好。每个“鸭子”包含一个 actionTypes.js , actionCreators.js , reducers.js , sagas.js和 selectors.js文件。这些文件中没有对其他鸭子的依赖,以避免循环依赖或 duck circle ,每个“鸭子”只包含它必须管理的逻辑。
然后,在根目录下我有一个 components和一个 containers文件夹和一些根文件:
components/ 文件夹包含我的应用程序的所有纯组件
containers/ 文件夹包含由上述纯组件创建的容器。当容器需要特定的 selector 时涉及很多“鸭子”,我把它写在我写 <Container/> 的同一个文件中组件,因为它是相对于这个特定容器的。如果selector跨多个容器共享,我在单独的文件中创建它(或在提供这些 Prop 的 HoC 中)。
rootReducers.js :通过组合所有 reducer 简单地暴露根 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
它让我们“隐藏”每只鸭子内部的状态形状 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
当我的“鸭子”够小的时候,我经常跳过文件夹的创建,直接写一个ducks/Books.js或 ducks/Taxonomies.js将所有这 5 个文件(actionTypes.js、actionCreators.js、reducers.js、selectors.js、sagas.js)合并在一起的文件。
关于javascript - Redux:组织容器、组件、 Action 和缩减器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38385861/
我知道您通常应该在Rails中使用新建/创建和编辑/更新之间的链接,但我有一个情况需要其他东西。无论如何我可以实现同样的连接吗?我有一个模型表单,我希望它发布数据(类似于新View如何发布到创建操作)。这是我的表格prohibitedthisjobfrombeingsaved: 最佳答案 使用:url选项。=form_for@job,:url=>company_path,:html=>{:method=>:post/:put} 关于ruby-on-rails-rails:Howtomak
我有一个rubyonrails应用程序。我按照facebook的说明添加了一个像素。但是,要跟踪转化,Facebook要求您将页面置于达到预期结果时出现的转化中。即,如果我想显示客户已注册,我会将您注册后转到的页面作为成功对象进行跟踪。我的问题是,当客户注册时,在我的应用程序中没有登陆页面。该应用程序将用户带回主页。它在主页上显示了一条消息,所以我想看看是否有一种方法可以跟踪来自Controller操作而不是实际页面的转化。我需要计数的Action没有页面,它们是ControllerAction。是否有任何人都知道的关于如何执行此操作的gem、文档或最佳实践?这是进入布局文件的像素
让多条路线去同一条路的最优雅的方式是什么ControllerAction?我有:get'dashboard',to:'dashboard#index'get'dashboard/pending',to:'dashboard#index'get'dashboard/live',to:'dashboard#index'get'dashboard/sold',to:'dashboard#index'这很丑陋。有什么“更优雅”的建议吗?一个类轮的奖励积分。 最佳答案 为什么不只有一个路由和一个Controller操作,并根据传递给它的参数来
我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的
我正在尝试在我的Controller中测试新操作。目前它看起来像这样:Controllerdefnew@business=Business.new@business.addresses.buildend规范describe'GET#new'doit'assignsanewbusinessto@business'doget:newexpect(assigns(:business)).tobe_a_new(Business)endend我想测试“@business.addresses.build”这一行。我该怎么做?提前致谢! 最佳答案
我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan
我正在尝试升级到Rails4beta1,但遇到了一些问题。简而言之,这就是我的应用程序Controller的样子。classApplicationControllercaches_action在Rails4中移到了它自己的gem中,因此包含gem应该可以解决问题。gem"actionpack-action_caching",github:"rails/actionpack-action_caching"但是当我运行我的请求规范或在浏览器中访问该应用程序时,我收到此错误。app/controllers/application_controller.rb:3:in`':undefinedm
我看到有关未找到文件min.map的错误消息:GETjQuery'sjquery-1.10.2.min.mapistriggeringa404(NotFound)截图这是从哪里来的? 最佳答案 如果ChromeDevTools报告.map文件的404(可能是jquery-1.10.2.min.map、jquery.min.map或jquery-2.0.3.min.map,但任何事情都可能发生)首先要知道的是,这仅在使用DevTools时才会请求。您的用户不会遇到此404。现在您可以修复此问题或禁用sourcemap功能。修复:获取文
我有一个用Rails3编写的站点。我的帖子模型有一个名为“内容”的文本列。在帖子面板中,html表单使用tinymce将“content”列设置为textarea字段。在首页,因为使用了tinymce,post.html.erb的代码需要用这样的原始方法来实现。.好的,现在如果我关闭浏览器javascript,这个文本区域可以在没有tinymce的情况下输入,也许用户会输入任何xss,比如alert('xss');.我的前台会显示那个警告框。我尝试sanitize(@post.content)在posts_controller中,但sanitize方法将相互过滤tinymce样式。例如
我一直在Heroku上尝试不同的缓存策略,并添加了他们的memcached附加组件,目的是为我的应用程序添加Action缓存。但是,当我在我当前的应用程序上查看Rails.cache.stats时(安装了memcached并使用dalligem),在执行应该缓存的操作后,我得到current和total_items为0。在Controller的顶部,我想缓存我有的Action:caches_action:show此外,我修改了我的环境配置(对于在Heroku上运行的配置)config.cache_store=:dalli_store我是否可以查看其他一些统计数据,看看它是否有效或我做错