Javascript React JS 服务器端问题 - 找不到窗口
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38951721/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
React JS Server side issue - window not found
提问by Jan Omacka
Hi I'm trying to use react-rte in my reactJS project. I have server side rendering and every time I want to use this package I get:
嗨,我正在尝试在我的 reactJS 项目中使用 react-rte。我有服务器端渲染,每次我想使用这个包时,我都会得到:
return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
^
ReferenceError: window is not defined
I guess the problem might be with isomorphic-tools but I don't know how to defer importing package to the client where window is going to be defined already.
我想问题可能出在同构工具上,但我不知道如何将导入包推迟到已经定义窗口的客户端。
采纳答案by Tony Tai Nguyen
If you're doing server side rendering, there's a good chance that the global window object is going to be undefined because that is only something the client will understand.
如果您正在进行服务器端渲染,那么全局窗口对象很有可能是未定义的,因为这只是客户端会理解的东西。
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!
注意:最初,当你启动你的项目时,它会渲染出一个完整的 DOM 字符串(此时它不会知道,
window
因为它是服务器端,但是然后用你的客户端代码重新渲染窗口对象将可用!
There is a workaround that I am using in this case. This is what I have for my webpack plugin:
在这种情况下,我正在使用一种解决方法。这是我的 webpack 插件:
new webpack.DefinePlugin({
'process.env.NODE_ENV': isDevelopment ? '"development"' : '"production"',
'process.env.BROWSER': JSON.stringify(true),
__DEV__: isDevelopment
}),
So I use process.env.BROWSER
to my advantage because it will be defined as undefined
if it is server side, and it will be true
if the client side is done rendering.
所以我利用process.env.BROWSER
我的优势,因为它将被定义为undefined
好像是服务器端,true
如果客户端完成渲染,它将被定义。
Since everything just stops working when there isn't a window object on the server side we can add this:
由于当服务器端没有窗口对象时一切都停止工作,我们可以添加以下内容:
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());
};
That way, your console won't scream at you and doesn't stop the server side rendering, to which you can now carry on with your glorious day! Although I have to admit that this is a bit Hacky, but it gets the job done because all we want to do is let the server side render out the initial DOM string and then let the client-side take over.
这样,您的控制台就不会对您大喊大叫,也不会停止服务器端渲染,您现在可以继续美好的一天!虽然我不得不承认这有点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.
另请注意:不要担心将窗口设置为空对象,一旦客户端完成渲染,它就会恢复正常。
回答by Natrezim
Here is a npm library which can handle window, document and global object for you: Global.
这是一个可以为您处理窗口、文档和全局对象的 npm 库:Global。
Then you can safely write:
然后你可以安全地写:
import window from 'global'
const mySpecialWindowFunction = () => {
return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
};
回答by Littlee
When doing server-side-rendering, global like window
, document
will be undefined. And if you want to do it in isomorphic way, you have to test what environment is when rendering componets.
在进行服务器端渲染时,全局 like window
,document
将是未定义的。如果你想以同构的方式来做,你必须测试渲染组件时的环境。
https://github.com/DavidWells/isomorphic-react-example
https://github.com/DavidWells/isomorphic-react-example
many example codes can be found on github, the link above is one of them, hope it can be helpful.
在github上可以找到很多示例代码,上面的链接就是其中之一,希望对您有所帮助。
回答by Dariusz Wo?niak
I've been using ReactJS.NET targeting build to client and server, and got the same problem.
我一直在使用 ReactJS.NET 目标构建到客户端和服务器,并遇到了同样的问题。
The solution is to set output.globalObject
to 'this'
.
解决方法是设置output.globalObject
为'this'
。
module.exports = {
// ...
output: {
// ...
globalObject: 'this'
}
};
Without that option set, it's falling back to window
which is working on client-only code.
如果没有设置该选项,它将退回到window
仅处理客户端代码。
回答by Jkarttunen
For anyone else trying to figure why their SSR fails even though they are checking if window object is undefined.
对于任何试图弄清楚为什么他们的 SSR 失败的人,即使他们正在检查 window 对象是否未定义。
You need to check if the window reference exists, not if it's value is null!
您需要检查窗口引用是否存在,而不是它的值是否为空!
if (typeof window === 'undefined) console.log('Window is not there')
Your window &&
and if (window)
checks with are failing because in JavaScript not declared and 'undefined' are different things.
您的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
And answer to the original question is that whenever accessing that need 'window' object, you need to make them conditional:
原始问题的答案是,无论何时访问需要“窗口”的对象,您都需要将它们设置为有条件的:
return (typeof window === 'undefined) ?
'node' :
/msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
回答by Vinayak humberi
I tried setting it in my constants as a global import:
我尝试在我的常量中将它设置为全局导入:
export const GLOBAL_WINDOW = (typeof self === 'object' && self.self === self && self) || (typeof global === 'object' && global.global === global && global) || this;
In this case it returns window or global object depending on weather your running it on client application or server.
在这种情况下,它根据您在客户端应用程序或服务器上运行它的天气返回窗口或全局对象。
Now you need to import this constant wherever you want to make use of window object.
现在你需要在任何你想使用 window 对象的地方导入这个常量。
Ex:
前任:
import { GLOBAL_WINDOW } from '../constants/Constants';
const user = JSON.parse(GLOBAL_WINDOW.localStorage.getItem('user'));
回答by Alan
Another solution I found, is that you can assign your state variables with your 'window variables' in the 'componentDidMount' event, and in the 'render' method you can test if the state variables you want are null or undefined then return null, until the 'componentDidMount' finish.
我发现的另一个解决方案是,您可以在“componentDidMount”事件中使用“窗口变量”分配状态变量,并在“render”方法中测试您想要的状态变量是否为空或未定义,然后返回空值,直到“componentDidMount”完成。