React 中的全局变量
Global variables in React
我知道 Redux 可以解决这个问题,但我想出了一个主意。
想象一下,我有一个应用程序在启动时获得一些 JSON。基于此 JSON 我正在设置环境,因此我们假设应用程序启动并下载列表项数组。
当然,因为我没有使用 Redux(应用程序本身非常简单,Redux 在这里感觉像是一个巨大的矫枉过正)如果我想在我的组件之外使用这些列表项,我必须将它们作为 props 传递下去然后将它们作为道具再次传递到我想使用它们的深度。
为什么我不能这样做:
fetch(listItems)
.then(response => response.json())
.then(json => {
window.consts = json.list;
这样我就可以在我的应用程序中的任何地方甚至在 React 之外访问我的列表。它被认为是反模式吗?当然,列表项永远不会更改,因此没有交互或状态更改。
从React的角度来看:
您可以通过 Context
从顶级传递列表,您可以查看文档 here。
使用它的示例很简单并且存在于许多库中,例如Material UI components使用它在所有组件中注入主题。
从的工程理念出发,一切都是的交易:
如果您觉得它会花费很多时间,而且您永远不会更改它,那么请保持简单,将其设置为 window
并记录下来。 (为了你自己不要忘记它,让其他人知道你为什么这样做。)
如果你绝对确定它们永远不会改变,我认为将它们存储在全局中是完全可以的,尤其是当你需要在 React 之外访问数据时。您可能想使用不同的名称,例如 "appNameConfig"..
另外,React有一个叫做Context的特性,也可以用于"deep provision" - Reference
当我有一些静态数据(但通过 API 请求)数据时,我通常做的是一种类似于全局但在常规导入下的小服务:
// get-timezones.js
import { get } from '../services/request'
let fetching = false
let timez = null
export default () => {
// if we already got timezones, return it
if (timez) {
return new Promise((resolve) => resolve(timez))
}
// if we already fired a request, return its promise
if (fetching) {
return fetching
}
// first run, return request promise
// and populate timezones for caching
fetching = get('timezones').then((data) => {
timez = data
return timez
})
return fetching
}
然后在视图中反应组件:
// some-view.js
getTimezones().then((timezones) => {
this.setState({ timezones })
})
它的工作方式总是 return 一个承诺,但第一次调用它时,它会向 API 发出请求并获取数据。后续请求将使用缓存变量(有点像全局变量)。
您的方法可能存在一些问题:
- 如果在此
window.consts
填充之前反应呈现,您将不会
能够访问它,React 不会知道它应该重新渲染。
- 即使数据不会被使用,你似乎也在做这个请求。
我的方法唯一的缺点是异步设置状态,如果不再安装组件可能会导致错误。
我知道 Redux 可以解决这个问题,但我想出了一个主意。
想象一下,我有一个应用程序在启动时获得一些 JSON。基于此 JSON 我正在设置环境,因此我们假设应用程序启动并下载列表项数组。
当然,因为我没有使用 Redux(应用程序本身非常简单,Redux 在这里感觉像是一个巨大的矫枉过正)如果我想在我的组件之外使用这些列表项,我必须将它们作为 props 传递下去然后将它们作为道具再次传递到我想使用它们的深度。
为什么我不能这样做:
fetch(listItems)
.then(response => response.json())
.then(json => {
window.consts = json.list;
这样我就可以在我的应用程序中的任何地方甚至在 React 之外访问我的列表。它被认为是反模式吗?当然,列表项永远不会更改,因此没有交互或状态更改。
从React的角度来看:
您可以通过 Context
从顶级传递列表,您可以查看文档 here。
使用它的示例很简单并且存在于许多库中,例如Material UI components使用它在所有组件中注入主题。
从的工程理念出发,一切都是的交易:
如果您觉得它会花费很多时间,而且您永远不会更改它,那么请保持简单,将其设置为 window
并记录下来。 (为了你自己不要忘记它,让其他人知道你为什么这样做。)
如果你绝对确定它们永远不会改变,我认为将它们存储在全局中是完全可以的,尤其是当你需要在 React 之外访问数据时。您可能想使用不同的名称,例如 "appNameConfig"..
另外,React有一个叫做Context的特性,也可以用于"deep provision" - Reference
当我有一些静态数据(但通过 API 请求)数据时,我通常做的是一种类似于全局但在常规导入下的小服务:
// get-timezones.js
import { get } from '../services/request'
let fetching = false
let timez = null
export default () => {
// if we already got timezones, return it
if (timez) {
return new Promise((resolve) => resolve(timez))
}
// if we already fired a request, return its promise
if (fetching) {
return fetching
}
// first run, return request promise
// and populate timezones for caching
fetching = get('timezones').then((data) => {
timez = data
return timez
})
return fetching
}
然后在视图中反应组件:
// some-view.js
getTimezones().then((timezones) => {
this.setState({ timezones })
})
它的工作方式总是 return 一个承诺,但第一次调用它时,它会向 API 发出请求并获取数据。后续请求将使用缓存变量(有点像全局变量)。
您的方法可能存在一些问题:
- 如果在此
window.consts
填充之前反应呈现,您将不会 能够访问它,React 不会知道它应该重新渲染。 - 即使数据不会被使用,你似乎也在做这个请求。
我的方法唯一的缺点是异步设置状态,如果不再安装组件可能会导致错误。