1

I am trying to set the initialState of my redux store from the NodeJS server. I am unsure on what I missed and how to get it to work.

Here's my server.js

const express = require('express');
const path = require('path');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const webpackHotServerMiddleware = require('webpack-hot-server-middleware');
const config = require('./webpack/webpack.development.config.js');
const compiler = webpack(config);
const app = express();

app.use(webpackHotMiddleware(compiler.compilers.find(
    compiler => compiler.name === 'client'
)));
app.use(webpackHotServerMiddleware(compiler));
app.listen(3000);

Here's my webpack.development.config

const path = require('path');
module.exports = [
{
    name: 'client',
    target: 'web',
    entry: './routes/client.jsx',
    output: {
        path: path.join(__dirname, 'assets'),
        filename: 'client.js',
        publicPath: '/assets/',
    },
    resolve: {
        extensions: ['.js', '.jsx']
    },
    devtool: 'source-map',
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /(node_modules\/)/,
                use: [
                    {
                        loader: 'babel-loader',
                    }
                ]
            },
            {
                test: /\.scss$/,
                use: [
                    {
                        loader: 'style-loader',
                    },
                    {
                        loader: 'css-loader',
                        options: {
                            modules: true,
                            importLoaders: 1,
                            localIdentName: '[name]__[local]___[hash:base64:5]',
                            sourceMap: true
                        }
                    },
                    {
                        loader: 'sass-loader'
                    }
                ]
            },
            { test: /\.html$/, loader: "html-loader" }
        ],
    },
},
];

PS, the same modules are there for server, but I've removed in an attempt to keep it short.

Here's the client.jsx

import React from 'react';
import { createStore } from 'redux'
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import Routes from './routes.jsx';
import { Provider } from 'react-redux';
import MainStore from '../views/store/MainStore';
import home from './home';

const store = createStore(MainStore, "Name");

ReactDOM.render((
    <Provider store={store}>
        <BrowserRouter>
            <Routes />
        </BrowserRouter>
    </Provider>
), document.getElementById('root'));

And finally my home.jsx

const express = require('express');
const path = require('path');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const webpackHotServerMiddleware = require('webpack-hot-server-middleware');
const config = require('../webpack/webpack.development.config.js');
const router = express();

router.get('/test', (req, res) => {
  res.json({ message: "I'm just testing to see if this works" });
});

const name = "Mona";

module.exports = {
  router: router,
  name: name,
};

I would like to import const name from home.jsx to client.jsx and set the initial value of the store as this imported value. I could do it manually by the line

const store = createStore(MainStore, "Name");

in client.jsx. But instead of using "Name" as a string, I would like to replace it with the constant value in home.jsx.

Any suggestions?

4
  • Try const store = createStore(MainStore, home.name); Commented Nov 29, 2017 at 3:48
  • @JeffF. I've already tried that, when I include "import home from './home';" in client.jsx, my webpack compilation fails with bombarding me with messages like Can't resolve 'fs'/'modules' and many such can't resolve messages from node-module files. Since they are excluded in webpack, I assumed I am doing some incorrect import. Commented Nov 29, 2017 at 3:58
  • I don't have too much experience with isomorphic, but seems like your client side code is trying to import your server side code, which naturally won't work. The 'fs' module is related to the file system, which the client side can't access. Commented Nov 29, 2017 at 4:29
  • @JeffF. That explains why "import home from './home';" in client.jsx is breaking the application. Can you suggest of any other alternative ways in which I can set my redux store from NodeJS? Commented Nov 29, 2017 at 4:58

1 Answer 1

1

Set initial state of store in an isomorphic react-redux app

Typical solution for supposed task is using preloaded state, which had been calculated at SSR phase and injected as serialized informational field in rendered HTML-template. Also you can create dedicated resource, like /api/initialState.js, which create initial state for your view model, dependent on client-side request and maybe JWT credentials.

You can see similar solution in resolve-scripts npm package, which provides ability for full-automatic isomorphic storage for redux on server, including SSR.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.