Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to properly deal with window=undefined error in react server side rendering

I'm using websockets on the browser which use the window object. But since i'm using server-side rendering with react. my server crashes and raises the below error when compiling

 [Error] ReferenceError: window is not defined

particularly because one of my components require the client-socket for communication with the server.

Ive tried adding the below code at the start of the my server.js file

if (typeof(window) == 'undefined'){
    global.window = new Object();
}

but it still raises the error for some reason. What else can i be doing? Has anyone dealt with this issue?

UPDATE - the problem might not be only specific to socket. Basically , i'm importing couple of objects from the below file in my component

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')
)

in my component

import React from 'react';
import Skill from './skill';
import Select from 'react-select';
import {socket ,store} from '../../client/index';

i'm getting the error because for some reason. the server is also looking at window.__INITIAL_STATE__ as well. So the problem is i cannot seem to import anything from the index.js file on the client side.

What can i do?

like image 959
Kannaj Avatar asked Sep 20 '25 03:09

Kannaj


1 Answers

Javascript doesn't necessarily have a compilation phase. Granted, most implementations do compile, but there isn't a single phase in which this happens. The access to the window variable does not throw until it is executed.

When using React, the normal way to run code only on the client is to put it inside componentDidMount.

In any case I would advise to not attempt to create fake versions of client-side APIs on the server to prevent breakage. Instead, make sure your client-side code only ever runs on the client.

You could wrap it in a function and call it only from componentDidMount or you could test the environment.

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();
}

I should note that server side code should preferably never be shipped to the client for reasons of security and code size. It is better to initialize the store from code that won't be available on the client at all.

There is no one way to do these things and there are pros and cons for each method.

Dan Abramov, the creator of Redux, I believe is a big proponent of knowing the reasons for every piece of code you have, to understand the libraries you use, and to prefer a method you understand over an accepted standard method. Redux itself is heavily based on these ideas which is why it doesn't prescribe much. It's also why there is such a teeming add-on community around Redux.

There really is no need to force all code to be compatible with both the server and the client. Just separate the parts that necessarily must be separate.

like image 79
DDS Avatar answered Sep 21 '25 17:09

DDS