在我的React应用程序中,我需要存储一些需要几乎无处可访问的数据,但不希望将其保存在全局(即静态)数据结构中,以便可以轻松模拟我的单元测试和风格指南。
我的意思是数据:
IN_BROWSER
,在浏览器版本中为true
,在节点中为false
。IS_MOBILE
现在我有一个名为sessionData.js
的文件来存储这些数据,每当我需要时,我会在代码中require('./sessionData')
使用它。我可以使用rewire
为我的单元测试模拟它,并且,因为它们顺序运行,它现在可以正常工作。风格指南存在问题,因为每个示例都可以从不同用户的角度显示视图(理想情况下,每个示例都有自己的sessionData
)。
IN_BROWSER
目前是global
,这也是一个坏主意,因为它会对每个模块的初始化代码产生隐式依赖。
我看到我可以通过道具将我的sessionData
和其他内容传递给层次结构中的每个组件,但这似乎有很多冗余。
是否有任何设计模式可以更好地解决它?
答案 0 :(得分:1)
我使用Webpack,有一个名为DefinePlugin
的插件可以处理这个问题。
我想这是一个很好的做法,因为它是我放置大部分应用配置细节的地方。
例如,我的webpack配置包含:
new webpack.DefinePlugin({
'process.env': {'NODE_ENV': JSON.stringify(options.env)}
}),
所以我可以像前端一样在前端使用process.env.NODE_ENV
。
我在这里打开了我的webpack配置:https://github.com/agendor/react-webpack-sample/blob/master/webpack.config.js
这是一个link for the plugin documentation
对于单元测试,我使用一个test-helper.js
类定义一些全局变量,我在每次测试开始时都需要它。我不确定这是不是一个好的做法,但它对我们的项目工作正常。我们在没有webpack的情况下运行测试。也许更好的做法是为处理其中一些全局变量的测试提供特定的webpack配置。
答案 1 :(得分:1)
如果我正确理解你,为什么不通过道具将数据结构传递给可能需要它的所有组件?显然你不能通过道具来修改它,但在这个数据结构中你总是可以包含一个回调函数来更新它,具有如下结构的东西:
structure = {
dataItem1: stuff,
dataItem2: stuff2,
dataItemCallback: { var foo = stuff here; }
}
然后你可以这样称呼:
this.props.structure.dataItem1;
this.props.structure.dataItem2;
要更新您可以随时致电的内容:
this.props.structure.dataItemCallback(newData);
此外,如果您通过道具传递它,现在所有组件都可以重新渲染,如果结构中的任何内容发生变化。
答案 2 :(得分:0)
看起来react context
是可行的方法。
不幸的是,API目前不稳定,例如React.withContext
在0.13-alpha中被弃用,文档说API将来会发生变化,但似乎是这样的上下文isn't going to be deprecated。
答案 3 :(得分:0)
在某些情况下,可以重构组件以直接传递所需的数据,而不是将其置于全局状态。这不能解决问题,但可以大大减少它。这是一个nice explanation from Dan Abramov: