olebedev/go-starter-kit

SSR and store changes

tanis2000 opened this issue · 4 comments

I'm experiencing an issue with SSR that's driving me mad. I've added authentication to this app and I'm storing a cookie with the auth token (JWT). The token is being passed down the pipe to the Go server so that I can actually send it to the JSVM when performing server side rendering.

This is working fine as the value of the cookie is available in the VM and I can read and log it to the console to check that it's actually there.

I then changed the toString.js to dispatch my loginSuccess action creator when the token is available.

My toString is the following:

import React from 'react';
import { Provider } from 'react-redux';
import { renderToString } from 'react-dom/server';
import { match, RouterContext } from 'react-router';
import Helmet from 'react-helmet';
import cookie from 'react-cookie';
import createRoutes from './routes';
import { createStore, setAsCurrentStore } from '../store';

/**
 * Handle HTTP request at Golang server
 *
 * @param   {Object}   options  request options
 * @param   {Function} cbk      response callback
 */
export default function (options, cbk) {
  cbk = global[cbk];
  let result = {
    uuid: options.uuid,
    app: null,
    title: null,
    meta: null,
    initial: null,
    error: null,
    redirect: null,
    token: options.token,
  };

  const store = createStore();
  setAsCurrentStore(store);

  try {
    match({ routes: createRoutes({store, first: { time: false }}), location: options.url }, (error, redirectLocation, renderProps) => {
      try {
        if (error) {
          result.error = error;

        } else if (redirectLocation) {
          result.redirect = redirectLocation.pathname + redirectLocation.search;

        } else {

          console.log('token');
          let token = options.token;
          console.log(options.token);
          if (token !== null) {
            store.dispatch(loginUserSuccess(token));
          }

          result.app = renderToString(
            <Provider store={store}>
              <RouterContext {...renderProps} />
            </Provider>
          );
          const { title, meta } = Helmet.rewind();
          result.title = title.toString();
          result.meta = meta.toString();
          result.initial = JSON.stringify(store.getState());
        }
      } catch (e) {
        result.error = e;
      }
      return cbk(result);
    });
  } catch (e) {
    result.error = e;
    return cbk(result);
  }
}

The problem is that the store.dispatch(loginUserSuccess(token)); line is breaking something even though there's no error or warning anywhere.
Basically if I try to access directly http://localhost:5001/usage the response of the /api/v1/system/conf call is completely missing. If I remove that line it works again but then all my authentication flow is being ignored just like I was an anonymous user.

What am I doing wrong?

Could you paste loginUserSuccess function here?

export function loginUserSuccess(token) {
  cookie.save('token', token);
  return {
    type: LOGIN_USER_SUCCESS,
    payload: {
      token: token,
    }
  };
}

Actually I kind of solved this issue by moving that code to the onEnter function on the main App component:

  static onEnter({store, nextState, replaceState, callback}) {
    let token = cookie.load('token');
    if (token !== null && token !== '') {
      store.dispatch(loginUserSuccess(token));
    }
    callback();
  }

It looks like the real issue was the one I opened in gojax. The missing headers caused the server side fetch to fail at calling the authenticated functions as the bearer token was completely missing just like all the other headers. I'm going to submit a PR for gojax and eventually this should solve as well. I'll keep you posted.

olebedev/gojax#1 is closed. Is this still an issue? Seems like good info to keep around, nonetheless.

@grokbot this is no longer an issue as the fix to gojax actually fixed this as well. The problems were intertwined. I'm going to close this issue.