我在浏览器上使用使用窗口对象的websockets。但是因为我正在使用带有 react 的服务器端渲染。我的服务器崩溃并在编译时引发以下错误
[Error] ReferenceError: window is not defined
特别是因为我的一个组件需要客户端套接字才能与服务器通信。
我尝试在我的server.js
文件的开头添加以下代码
if (typeof(window) == 'undefined'){
global.window = new Object();
}
但由于某种原因,它仍然会引发错误。我还能做什么?有人处理过这个问题吗?
更新 - 问题可能不仅特定于套接字。基本上,我正在从组件中的以下文件导入几个对象
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import {createStore} from 'redux';
import { Router, Route, browserHistory ,IndexRoute} from 'react-router'
import routes from '../shared/routes/routes';
import rootReducer from '../shared/reducers/index';
import SocketCluster from 'socketcluster-client';
const initialState = window.__INITIAL_STATE__
export const store = createStore(rootReducer,initialState)
const options = {
port: 3000
}
if(store.getState().User.isAuthenticated){
const socket = SocketCluster.connect(options)
}
console.log(store.getState())
ReactDOM.render(
<Provider store={store}>
<Router history={browserHistory}>
{routes}
</Router>
</Provider>
,document.getElementById('app')
)
在我的组件中
import React from 'react';
import Skill from './skill';
import Select from 'react-select';
import {socket ,store} from '../../client/index';
我收到错误,因为出于某种原因。 服务器也在查看window.__INITIAL_STATE__
。所以问题是我似乎无法从客户端的索引.js文件中导入任何内容。
我能做什么?
Javascript 不一定有编译阶段。当然,大多数实现确实可以编译,但没有一个阶段会发生这种情况。对 window
变量的访问在执行之前不会引发。
使用 React 时,仅在客户端上运行代码的正常方法是将其放在 componentDidMount
中。
无论如何,我建议不要尝试在服务器上创建客户端API的虚假版本以防止损坏。相反,请确保客户端代码仅在客户端上运行。
您可以将其包装在函数中并仅从componentDidMount
调用它,也可以测试环境。
function clientInitialize() {
// start your client side app here
// create client-side store here
}
function serverInitialize() {
// create server-side store here
}
if (typeof window === 'object') {
clientInitialize();
} else {
serverInitialize();
}
我应该注意,出于安全性和代码大小的原因,服务器端代码最好永远不要传送到客户端。最好从客户端上根本不可用的代码初始化存储。
没有一种方法可以做这些事情,每种方法都有优点和缺点。
Dan Abramov,Redux的创建者,我相信他非常支持了解你拥有的每一段代码的原因,理解你使用的库,以及更喜欢你理解的方法而不是公认的标准方法。Redux本身在很大程度上基于这些想法,这就是为什么它没有规定太多。这也是为什么在Redux周围有如此庞大的附加社区的原因。
实际上没有必要强制所有代码都与服务器和客户端兼容。只需将必须分开的部分分开即可。