Sunday, 14 May 2017

Getting " React.createElement: type is invalid " at RoutingContext(...renderProps) in server side code

I am beginner in react. I'm trying to work on a breaking project written in node and react. I am stuck at this place. the server tries to render using routingContext but fails and gives me this error.

Warning: React.createElement: type is invalid -- expected a string (for 
built-in components) or a class/function (for composite components) but got: 
undefined. You likely forgot to export your component from the file it's 
defined in.
Invariant Violation: Element type is invalid: expected a string (for built-
in components) or a class/function (for composite components) but got: 
undefined. You likely forgot to export your component from the file it's 
defined in.

I think i'm missing out on something silly. here is my code at server side.

import DocumentTitle from '../../client/components/Title';
import Html from './html.react';
import React from 'react';  
import ReactDOMServer from 'react-dom/server';
import config from '../config';
import useragent from 'useragent';
import HOT_RELOAD_PORT from '../../../webpack/constants'; 
import {IntlProvider} from 'react-intl';
import {Provider} from 'react-redux';
import {RoutingContext, match} from 'react-router';
import serialize from 'serialize-javascript';
import Promise from 'bluebird';
import {configureStore} from '../../common';
import {mapDispatchToProps} from '../../common';

import createRoutes from '../../client/createRoutes.js';
import {createMemoryHistory} from 'history';

import { createServerRenderContext, ServerRouter } from 'react-router';

import loopback from 'loopback';
import app from '../main';

export default function render(req, res, next) {
 const ctx = loopback.getCurrentContext();
 const currentUser = ctx && ctx.get('currentUser');
 let initialState = {
   device: {
     isMobile: ['phone', 'tablet'].indexOf(req.device.type) > -1
   },
   users: {
     viewer: currentUser ? ctx.get('currentUser') : null
   }
 };

 // provide auth token id to client
 if (currentUser) {
   initialState.users.viewer.authToken = ctx.get('accessToken').id;
 }

 const store = configureStore({initialState});

 const {actions} = mapDispatchToProps(store.dispatch);
 actions.setAppBaseUrl(app.get('baseUrl'));

 // Fetch logged in user here because routes may need it. Remember we can 
 use
 // store.dispatch method.
 const routes = createRoutes(() => store.getState());
 const location = createMemoryHistory().createLocation(req.url);

  match({routes, location}, (error, redirectLocation, renderProps) => {

  if (redirectLocation) {
    res.redirect(301, redirectLocation.pathname + redirectLocation.search);
   return;
  }

  if (error) {
    next(error);
    return;
  }

// // Not possible with * route.
// if (renderProps == null) {
//   res.send(404, 'Not found');
//   return;
// }

 fetchComponentData(store.dispatch, req, renderProps, store.getState())
   .then(() => renderPage(store, renderProps, req))
   .then(html => res.send(html))
   .catch(next);
 });
}

function fetchComponentData(dispatch, req, {components, location, params}, 
{app, users}) {
  console.log("components ", components);
  const fetchActions = components.reduce((actions, component) => {
  return actions.concat(component.fetchAction || []);
}, []);
  console.log("fetchedActions ", fetchActions);
  const promises = fetchActions.map(action => dispatch(action({
  location,
  params,
  app, users
 })));
 return Promise.all(promises); 
}

function renderPage(store, renderProps, req) {
  const clientState = store.getState();
  const {headers, hostname} = req;
  const scriptHtml = getScriptHtml(clientState, headers, hostname);
  const appHtml = getAppHtml(store, renderProps);


  return '<!DOCTYPE html>' + ReactDOMServer.renderToStaticMarkup(
   <Html
    appCssHash={config.assetsHashes.appCss}
    bodyHtml={`<div id="app">${appHtml}</div>${scriptHtml}`}
    googleAnalyticsId={app.get('googleAnalyticsId')}
    isProduction={config.isProduction}
    title={DocumentTitle.rewind()}
    />
  );
 }

 function getAppHtml(store, renderProps) {

 return ReactDOMServer.renderToString(
   <Provider store={store}>
     <IntlProvider>
        <RoutingContext {...renderProps} />
     </IntlProvider>
   </Provider>
 );
}

function getScriptHtml(clientState, headers, hostname) {
   let scriptHtml = '';

   const ua = useragent.is(headers['user-agent']);
   const needIntlPolyfill = ua.safari || (ua.ie && ua.version < '11');
   if (needIntlPolyfill) {
   scriptHtml += `
     <script src="/node_modules/intl/dist/Intl.min.js"></script>
     <script src="/node_modules/intl/locale-data/jsonp/en-US.js"></script>
   `;
 }

 const appScriptSrc = config.isProduction
   ? '/_assets/app.js?' + config.assetsHashes.appJs
   : `//${hostname}:${HOT_RELOAD_PORT}/build/app.js`;

 // Note how clientState is serialized. JSON.stringify is anti-pattern.
 // https://github.com/yahoo/serialize-javascript#user-content-automatic-
    escaping-of-html-characters
 return scriptHtml + `
   <script>
      window.__INITIAL_STATE__ = ${serialize(clientState)};
   </script>
   <script src="${appScriptSrc}"></script>
 `;
 }



via Thousif Jowhar

No comments:

Post a Comment