您的组件必须在 reduxProvider
组件内才能使用 redux 钩子useSelector
和useDispatch
/或connect
HOC。
在一个典型的 React 应用程序中,你可以将它Provider
放在你的App
组件中,它是所有东西的父级。但是 Gatsby 使用了不同的设置,每个页面都是完全独立的,所以没有共享的父页面可以放置Provider
.
Gatsby拥有的是一个 API,用于通过在配置文件中定义函数来覆盖自定义行为。您可以将一堆文件放在应用程序的根目录中,package.json
与src
. 我们将在这里使用的两个是gatsby-browser.js
,它控制客户端,以及gatsby-ssr.js
,它控制通过服务器端渲染创建静态 HTML 页面。这两个文件都支持一个名为wrapRootElement
.
我们使用该wrapRootElement
函数将我们的 Redux 提供程序作为每个页面的包装器。由于我们在两个文件中使用相同的函数,因此官方的“using-redux”示例在单独的文件中定义了该函数并将其导入到两个配置中。wrap-with-provider.js
不是一个特殊的文件名,它只是函数的持有者。
一个wrapRootElement
函数接收element
一个类似于 prop 的children
prop。我们的函数创建一个 store 实例并返回一个Provider
带有element
作为其子元素的 store 的 a。我们在这个函数中创建了 store,所以如果你当前的 redux 文件正在导出一个 createdstore
作为常量,你需要导出一个创建 store 的可调用函数。你可以在这里看到他们的例子。
用-provider.js 包装
import React from "react"
import { Provider } from "react-redux"
import createStore from "./src/state/createStore"
// eslint-disable-next-line react/display-name,react/prop-types
export default ({ element }) => {
// Instantiating store in `wrapRootElement` handler ensures:
// - there is fresh store for each SSR page
// - it will be called only once in browser, when React mounts
const store = createStore()
return <Provider store={store}>{element}</Provider>
}
同样,此文件本身不会操纵 Gatsby 行为。我们需要导出它的值并将其分配给配置文件中的特殊变量来执行此操作。以下是这些文件:
盖茨比浏览器.js
import wrapWithProvider from "./wrap-with-provider"
export const wrapRootElement = wrapWithProvider
盖茨比-ssr.js
import wrapWithProvider from "./wrap-with-provider"
export const wrapRootElement = wrapWithProvider
两者的内容是一样的。我们所做的只是导入我们在其中创建的函数wrap-with-provider.js
并将其分配给wrapRootElement
控制行为的特殊命名变量。