我正在尝试使用 Remix 将一些环境变量输入浏览器,并且我一直在关注以下内容:
https://remix.run/docs/en/v1/guides/envvars
我已完全按照步骤 1 和 2 进行操作,但是我无法window.ENV从浏览器访问。我收到此错误:ReferenceError: window is not defined
这是我非常简单的组件:
function Test() {
console.log('Window: ', window);
return <div>Hello, Test</div>;
}
export default Test;
Run Code Online (Sandbox Code Playgroud)
如果我注释掉,我可以在文档顶部console.log看到和内容。但是取消注释会显示错误消息并且没有标签。这告诉我问题是来自文档的设置,而不是来自我的组件。<script><body>window.ENV = {...}console.log<script>window.ENV
任何想法将不胜感激!
Dan*_*ila 21
您无法访问window该代码中的对象(组件渲染),因为它既在服务器上运行(因为服务器端渲染)又在客户端上运行(就像常规客户端 React 应用程序一样)。服务器上没有window对象或任何其他浏览器 API。因此,您需要以这种方式编写代码,以便它可以在服务器和客户端上运行。
不过,您稍后仍然可以使用window对象,例如在useEffect某个onClick处理程序中,因为此代码只会在客户端运行:
// both this cases will work fine
useEffect(() => {
console.log(window.ENV);
}, []);
// ...
<button
onClick={() => {
console.log(window.ENV);
}}
>
Log env
</button>
Run Code Online (Sandbox Code Playgroud)
但有时您需要立即直接在渲染方法中使用这些环境值。您可以将loader函数与钩子结合使用useLoaderData,如下所示:
export function loader() {
// process.env is available here because loader runs only on the server side
return {
SOME_SECRET: process.env.SOME_SECRET
};
}
export default function Index() {
const data = useLoaderData();
// here you can use everything that you returned from the loader function
console.log(data.SOME_SECRET);
return <div>{/* ... */}</div>
}
Run Code Online (Sandbox Code Playgroud)
小智 9
使用 Remix 文档建议的模式的另一种方法是在 Remix paths/root.tsxwindow.ENV文件中创建根 React 上下文,其中在上下文的 value prop 中包含客户端环境变量。然后根据需要通过相应的钩子访问变量,而无需先使用。下面是一个使用 TypeScript 的简化示例:useRootContextuseEffect
上下文/根上下文.ts
import { createContext, useContext } from 'react'
export const RootContext = createContext({
stripePublicKey: '',
})
export const useRootContext = () => useContext(RootContext)
Run Code Online (Sandbox Code Playgroud)
路线/root.tsx
import { useLoaderData, type LoaderFunction, json } from 'remix'
import { RootContext } from '~/context'
export const loader: LoaderFunction = async () => {
return json({
ENV: {
stripePublicKey: process.env.STRIPE_PUBLIC_KEY,
},
})
}
const App = () => {
const { ENV } = useLoaderData()
return (
<html lang="en">
<body>
<RootContext.Provider
value={{
stripePublicKey: ENV.stripePublicKey,
}}
>
{/* app markup */}
</RootContext.Provider>
</body>
</html>
)
}
export default App
Run Code Online (Sandbox Code Playgroud)
访问通过useRootContext
import { useRootContext } from '~/context'
const BillingLayout = () => {
const { stripePublicKey } = useRootContext()
console.log(stripePublicKey)
return (<Outlet />)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11450 次 |
| 最近记录: |