javascript React JS服务器端问题-未找到窗口

1cklez4t  于 2023-10-14  发布在  Java
关注(0)|答案(8)|浏览(79)

你好,我正在尝试在我的reactJS项目中使用react-rte。我有服务器端渲染,每次我想使用这个包,我得到:

return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
                               ^
ReferenceError: window is not defined

我想问题可能是同构工具,但我不知道如何推迟导入包到客户端,其中窗口将被定义已经。

juud5qan

juud5qan1#

这里有一个npm库,可以为你处理窗口,文档和全局对象:Global
你可以放心地写:

import window from 'global'

const mySpecialWindowFunction = () => {
    return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
};
wko9yo5t

wko9yo5t2#

如果你在做服务器端的渲染,很有可能全局窗口对象是未定义的,因为这是客户端唯一能理解的。

**注意:**最初,当你启动你的项目时,它会呈现出你的DOM的一个完整的字符串(在这一点上,它不会知道window,因为它是服务器端的,但然后用你的窗口对象将可用的客户端代码重新呈现!

在这种情况下,我使用了一种变通方法。这就是我的webpack插件:

new webpack.DefinePlugin({
  'process.env.NODE_ENV': isDevelopment ? '"development"' : '"production"',
  'process.env.BROWSER': JSON.stringify(true),
  __DEV__: isDevelopment
}),

因此,我使用process.env.BROWSER来发挥我的优势,因为如果是服务器端,它将被定义为undefined,如果客户端完成渲染,它将被定义为true
由于当服务器端没有窗口对象时,一切都停止工作,我们可以添加以下内容:

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字符串,然后让客户端接管。

**另请注意:**不要担心将window设置为空对象,一旦客户端完成渲染,它将恢复正常。

gywdnpxw

gywdnpxw3#

对于其他人试图找出为什么他们的SSR失败,即使他们正在检查窗口对象是否未定义。

  • 您需要检查窗口引用是否存在,而不是它的值是否为空!*
if (typeof window === 'undefined') console.log('Window is not there')

您的window &&if (window)检查失败,因为在JavaScript中,未声明和未定义是不同的。

const a = undefined;
if (a) console.log('a');  // logs nothing, since 'a' is undefined
if (b) console.log('b');  // ReferenceError: b is not defined

而对最初问题的回答是,每当访问need 'window'对象时,都需要使它们成为条件:

return (typeof window === 'undefined') ?
   'node' :
   /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
acruukt9

acruukt94#

我一直在使用ReactJS.NET来构建客户端和服务器,也遇到了同样的问题。
解决方案是将output.globalObject设置为'this'

module.exports = {
  // ...
  output: {
    // ...
    globalObject: 'this'
  }
};

如果没有设置该选项,它将退回到window,它只处理客户端代码。

yruzcnhs

yruzcnhs5#

在进行服务器端渲染时,像windowdocument这样的全局变量将是未定义的。如果你想以同构的方式来做,你必须测试渲染组件时的环境。
https://github.com/DavidWells/isomorphic-react-example
在github上可以找到很多示例代码,上面的链接就是其中之一,希望对你有所帮助。

goucqfw6

goucqfw66#

我尝试在常量中将其设置为全局导入:

export const GLOBAL_WINDOW = (typeof self === 'object' && self.self === self && self) || (typeof global === 'object' && global.global === global && global) || this;

在这种情况下,它返回窗口或全局对象,这取决于你是在客户端应用程序还是服务器上运行它。
现在你需要在任何你想使用窗口对象的地方导入这个常量。
例如:

import { GLOBAL_WINDOW } from '../constants/Constants';

const user = JSON.parse(GLOBAL_WINDOW.localStorage.getItem('user'));
gr8qqesn

gr8qqesn7#

将窗口对象移动到useEffect()。

lp0sw83n

lp0sw83n8#

我发现的另一个解决方案是,你可以在'componentDidMount'事件中用'window variables'分配你的状态变量,在'render'方法中,你可以测试你想要的状态变量是null还是undefined,然后返回null,直到'componentDidMount'完成。

相关问题