React JS 服务器端问题 - window 未找到
React JS Server side issue - window not found
您好,我正在尝试在我的 reactJS 项目中使用 react-rte。我有服务器端渲染,每次我想使用这个包时,我都会得到:
return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
^
ReferenceError: window is not defined
我想问题可能出在同构工具上,但我不知道如何将包导入到已经定义 window 的客户端。
做服务器端渲染时,全局如window
、document
将是未定义的。而如果你想以同构的方式来做,你必须测试渲染组件时的环境。
https://github.com/DavidWells/isomorphic-react-example
在github上可以找到很多示例代码,上面的link就是其中之一,希望对您有所帮助。
如果您正在执行服务器端呈现,则全局 window 对象很有可能未定义,因为那只是客户端会理解的内容。
Note: Initially, when you start up your project its going to render out a complete string of your DOM (at this point it will not know about window
because it is server side, but then re-render with the client-side code to which your window object will be available!
在这种情况下,我使用了一种解决方法。这是我的 webpack 插件:
new webpack.DefinePlugin({
'process.env.NODE_ENV': isDevelopment ? '"development"' : '"production"',
'process.env.BROWSER': JSON.stringify(true),
__DEV__: isDevelopment
}),
所以我使用 process.env.BROWSER
对我有利,因为如果它是服务器端,它将被定义为 undefined
,如果客户端完成渲染,它将被定义为 true
。
因为当服务器端没有 window 对象时一切都会停止工作,我们可以添加:
const mySpecialWindowFunction = () => {
/* START HACK */
if (!process.env.BROWSER) {
global.window = {}; // Temporarily define window for server-side
}
/* END HACK */
return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
};
这样,您的控制台就不会对您尖叫,也不会停止服务器端渲染,您现在可以继续享受光荣的一天了!虽然我不得不承认这有点 Hacky,但它完成了工作,因为我们想要做的就是让服务器端呈现初始的 DOM 字符串和然后让客户端接管。
Also Note: Don't worry about setting window as an empty object, it will be back to normal once the client-side finishes rendering.
这是一个 npm 库,可以为您处理 window、文档和全局对象:Global.
那你就可以放心的写了:
import window from 'global'
const mySpecialWindowFunction = () => {
return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
};
我尝试在我的常量中将其设置为全局导入:
export const GLOBAL_WINDOW = (typeof self === 'object' && self.self === self && self) || (typeof global === 'object' && global.global === global && global) || this;
在这种情况下,它 returns window 或全局对象取决于天气 运行 它在客户端应用程序或服务器上。
现在你需要在任何你想使用 window 对象的地方导入这个常量。
例如:
import { GLOBAL_WINDOW } from '../constants/Constants';
const user = JSON.parse(GLOBAL_WINDOW.localStorage.getItem('user'));
我发现的另一个解决方案是,您可以在 'componentDidMount' 事件中使用 'window variables' 分配状态变量,并且在 'render' 方法中您可以测试状态变量是否你想要的是 null 或 undefined 然后 return null,直到 'componentDidMount' 完成。
我一直在使用 ReactJS.NET 目标构建到客户端和服务器,但遇到了同样的问题。
解决方法是将output.globalObject
设置为'this'
。
module.exports = {
// ...
output: {
// ...
globalObject: 'this'
}
};
如果没有设置该选项,它将退回到 window
,它正在处理仅客户端代码。
对于任何试图弄清楚为什么他们的 SSR 失败的人,即使他们正在检查 window 对象是否未定义。
您需要检查 window 引用是否存在,而不是它的值是否为空!
if (typeof window === 'undefined') console.log('Window is not there')
您的 window &&
和 if (window)
检查失败,因为 JavaScript 未声明和 'undefined' 是不同的东西。
const a = undefined;
if (a) console.log('a'); // logs nothing, since 'a' is undefined
if (b) console.log('b'); // ReferenceError: b is not defined
原始问题的答案是,每当访问需要 'window' 的对象时,您需要使它们成为条件:
return (typeof window === 'undefined') ?
'node' :
/msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
React 通过 'Suspense' 支持延迟加载,专门用于此类目的:
//add this to the top of your component
const RichTextEditor = React.lazy(() =>
import("react-rte").then((module) => ({ default: module.Editor }))
);
render(){
<Suspense fallback={<p>loading</p>}>
<RichTextEditor />
</Suspense>
}
您好,我正在尝试在我的 reactJS 项目中使用 react-rte。我有服务器端渲染,每次我想使用这个包时,我都会得到:
return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
^
ReferenceError: window is not defined
我想问题可能出在同构工具上,但我不知道如何将包导入到已经定义 window 的客户端。
做服务器端渲染时,全局如window
、document
将是未定义的。而如果你想以同构的方式来做,你必须测试渲染组件时的环境。
https://github.com/DavidWells/isomorphic-react-example
在github上可以找到很多示例代码,上面的link就是其中之一,希望对您有所帮助。
如果您正在执行服务器端呈现,则全局 window 对象很有可能未定义,因为那只是客户端会理解的内容。
Note: Initially, when you start up your project its going to render out a complete string of your DOM (at this point it will not know about
window
because it is server side, but then re-render with the client-side code to which your window object will be available!
在这种情况下,我使用了一种解决方法。这是我的 webpack 插件:
new webpack.DefinePlugin({
'process.env.NODE_ENV': isDevelopment ? '"development"' : '"production"',
'process.env.BROWSER': JSON.stringify(true),
__DEV__: isDevelopment
}),
所以我使用 process.env.BROWSER
对我有利,因为如果它是服务器端,它将被定义为 undefined
,如果客户端完成渲染,它将被定义为 true
。
因为当服务器端没有 window 对象时一切都会停止工作,我们可以添加:
const mySpecialWindowFunction = () => {
/* START HACK */
if (!process.env.BROWSER) {
global.window = {}; // Temporarily define window for server-side
}
/* END HACK */
return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
};
这样,您的控制台就不会对您尖叫,也不会停止服务器端渲染,您现在可以继续享受光荣的一天了!虽然我不得不承认这有点 Hacky,但它完成了工作,因为我们想要做的就是让服务器端呈现初始的 DOM 字符串和然后让客户端接管。
Also Note: Don't worry about setting window as an empty object, it will be back to normal once the client-side finishes rendering.
这是一个 npm 库,可以为您处理 window、文档和全局对象:Global.
那你就可以放心的写了:
import window from 'global'
const mySpecialWindowFunction = () => {
return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
};
我尝试在我的常量中将其设置为全局导入:
export const GLOBAL_WINDOW = (typeof self === 'object' && self.self === self && self) || (typeof global === 'object' && global.global === global && global) || this;
在这种情况下,它 returns window 或全局对象取决于天气 运行 它在客户端应用程序或服务器上。
现在你需要在任何你想使用 window 对象的地方导入这个常量。
例如:
import { GLOBAL_WINDOW } from '../constants/Constants';
const user = JSON.parse(GLOBAL_WINDOW.localStorage.getItem('user'));
我发现的另一个解决方案是,您可以在 'componentDidMount' 事件中使用 'window variables' 分配状态变量,并且在 'render' 方法中您可以测试状态变量是否你想要的是 null 或 undefined 然后 return null,直到 'componentDidMount' 完成。
我一直在使用 ReactJS.NET 目标构建到客户端和服务器,但遇到了同样的问题。
解决方法是将output.globalObject
设置为'this'
。
module.exports = {
// ...
output: {
// ...
globalObject: 'this'
}
};
如果没有设置该选项,它将退回到 window
,它正在处理仅客户端代码。
对于任何试图弄清楚为什么他们的 SSR 失败的人,即使他们正在检查 window 对象是否未定义。
您需要检查 window 引用是否存在,而不是它的值是否为空!
if (typeof window === 'undefined') console.log('Window is not there')
您的 window &&
和 if (window)
检查失败,因为 JavaScript 未声明和 'undefined' 是不同的东西。
const a = undefined;
if (a) console.log('a'); // logs nothing, since 'a' is undefined
if (b) console.log('b'); // ReferenceError: b is not defined
原始问题的答案是,每当访问需要 'window' 的对象时,您需要使它们成为条件:
return (typeof window === 'undefined') ?
'node' :
/msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
React 通过 'Suspense' 支持延迟加载,专门用于此类目的:
//add this to the top of your component
const RichTextEditor = React.lazy(() =>
import("react-rte").then((module) => ({ default: module.Editor }))
);
render(){
<Suspense fallback={<p>loading</p>}>
<RichTextEditor />
</Suspense>
}