ReactDOM.renderToString sessionStorage 未定义,窗口未定义 [英] ReactDOM.renderToString sessionStorage is not defined, window is not defined

查看:69
本文介绍了ReactDOM.renderToString sessionStorage 未定义,窗口未定义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,webpack 配置为模块打包器,babel 配置为我的 js 编译器.全部在节点引擎上.我确定当我运行 npm run dev 时会发生以下流程:

I have an application with webpack configured as a module bundler and babel as my js compiler. all on a node engine. I stetted up that when I run npm run dev the following flow will happen:

webpack-dev-server.js 将运行.文件如下:

const Express = require('express');
const webpack = require('webpack');
const webpackConfig = require('./dev.config');
const compiler = webpack(webpackConfig);

const host = 'localhost';
const port = 8080;
const serverOptions = {
  contentBase: `http://${host}:${port}`,
  quiet: true,
  noInfo: true,
  hot: true,
  inline: true,
  lazy: false,
  publicPath: webpackConfig.output.publicPath,
  headers: { 'Access-Control-Allow-Origin': '*' },
  stats: { colors: true },
};

const app = new Express();

app.use(require('webpack-dev-middleware')(compiler, serverOptions));
app.use(require('webpack-hot-middleware')(compiler));

app.listen(port, function onAppListening(err) {
  if (err) {
    console.error(err);
  } else {
    console.info('==> Webpack development server listening on port %s', port);
  }
});

然后是 server.js

require('./../server.babel');
const path = require('path');
const WebpackIsomorphicTools = require('webpack-isomorphic-tools');
const rootDir = path.resolve(require('../server/config').rootDir);

global.__CLIENT__ = false;
global.__SERVER__ = true;
global.__DEVELOPMENT__ = process.env.NODE_ENV !== 'production';

if (__DEVELOPMENT__) {
  if (!require('piping')({
    hook: true,
    ignore: /(\/\.|~$|\.json|\.scss$)/i
  })) {
    return;
  }
}

global.webpackIsomorphicTools = new WebpackIsomorphicTools(require('../webpack/webpack-isomorphic-tools'))
  .development(__DEVELOPMENT__)
  .server(rootDir, () => {
    require('../server/server');
  });

express 和 React 渲染:

express and React rendering:

import 'babel-polyfill';
// Server
import express from 'express';
import session from 'express-session';
import cookieParser from 'cookie-parser';
// React
import React from 'react';
import ReactDOM from 'react-dom/server';
import createHistory from 'react-router/lib/createMemoryHistory';
import { match } from 'react-router';
// Redux
import { Provider } from 'react-redux';
import { ReduxAsyncConnect, loadOnServer } from 'redux-connect';
import { syncHistoryWithStore } from 'react-router-redux';
import path from 'path';
import csurf from 'csurf';
import bodyParser from 'body-parser';
// Relative imports
import Html from '../shared/html';
import proxy from './proxy';
import createStore from '../shared/redux/create';
import { staticPath } from './config';
import { getRoutes } from '../shared/routes';

require('dotenv').config({
  path: path.resolve(__dirname, '../.env'),
});

const SERVER_PORT = process.env.SERVER_PORT;
const APP_SECRET = process.env.APP_SECRET;
const API_PORT = process.env.API_PORT;
const API_HOST = process.env.API_HOST;

function renderPage({ renderProps, store, res, client, csrfToken }) {
  loadOnServer({ ...renderProps, store, helpers: { client } })
    .then(() => {
      const component = (
        <Provider store={store} key="provider">
          <ReduxAsyncConnect {...renderProps} />
        </Provider>
      );
      res.status(200);
      res.send('<!doctype html>\n' +
        ReactDOM.renderToString(
          <Html
            assets={webpackIsomorphicTools.assets()}
            component={component}
            csrfToken={csrfToken}
            store={store}
          />,
        ),
      );
    })
    .catch((err) => {
      console.error(err.stack);
    });
}


const app = express();
const csrf = csurf();

// express middlewares
// app.use(favicon(path.resolve(__dirname, '../static/favicon.ico'))); @TODO favicon @ilanus
app.use(bodyParser.json());
app.use(express.static(staticPath));
app.use(cookieParser(APP_SECRET));
app.use(session({
  secret: APP_SECRET,
  saveUninitialized: true,
  resave: true,
}));
app.use(csrf);
app.use('/api', (req, res) => {
  if (!req.xhr) res.redirect('/');
  proxy.web(req, res, { target: `http://${API_HOST}:${API_PORT}` });
});
app.use((req, res) => {
  const csrfToken = req.csrfToken();
  if (__DEVELOPMENT__) {
    // Do not cache webpack stats: the script file would change since
    // hot module replacement is enabled in the development env
    webpackIsomorphicTools.refresh();
  }
  const memoryHistory = createHistory(req.originalUrl);
  const store = createStore({}, memoryHistory);
  const history = syncHistoryWithStore(memoryHistory, store);
  match({ history, routes: getRoutes(store), location: req.originalUrl },
    (error, redirectLocation, renderProps) => {
      if (redirectLocation) {
        res.redirect(redirectLocation.pathname + redirectLocation.search);
      } else if (error) {
        console.error('ROUTER ERROR:', error);
        res.status(500);
      } else if (renderProps) {
        renderPage({ renderProps, store, res, csrfToken });
      } else {
        res.status(404).send('Not found');
      }
    });
});

app.use((err, req, res) => {
  if (err === 'EBADCSRFTOKEN') {
    res.status(403);
    res.send('invalid csrf token');
  } else {
    res.status(500);
    res.send('Oops, internal server error');
  }
});

app.listen(SERVER_PORT, (error) => {
  if (error) {
    console.error(error);
  } else {
    console.info(`App started listening on port ${SERVER_PORT}`);
  }
});

现在每当我尝试 console.log('window', window, 'sessionStorage', sessionStorage);render() 函数或 componentDidMount() 我最终得到的反应组件: sessionStorage is not defined, window is not defined 错误.我想那是因为我在服务器端运行堆栈,而那些堆栈在那里不可用,我错过了什么?

Now whenever I try to console.log('window', window, 'sessionStorage', sessionStorage); within a render() function or componentDidMount() of a react component I end up with: sessionStorage is not defined, window is not defined errors. I guess that's because I am running the stack on the server-side and those are not available there what am I missing?

推荐答案

你只需要一个函数,而不是直接访问窗口和窗口属性,例如

You just need a function instead of accessing window and window properties directly, e g

function globalObj(){
    const isNode = typeof process === 'object' && process.versions && !!process.versions.node;

    return isNode ? global : window;
 }

您可以从那里以通用方式访问 sessionStorage 等而不会出错

You can the access sessionStorage etc from there in a universal way without errors

globalObj()["sessionStorage"]

希望有帮助.

这篇关于ReactDOM.renderToString sessionStorage 未定义,窗口未定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆