Server Side Rendering (SSR) in React 16 with create-react-app using Material Ui, Redux and Express Libraries

What is Server Side Rendering in React (SSR)?

Server side rendering is normally rendering the requested page at server side of client and sending back the whole html page from server.
i.e: Server-side rendering is all about handling the initial render whenever a request hits the server. For more on basics of SSR please read my first article

Let us see how to implement server side rendering in ReactJs

How to Enable Server Side Rendering using React and ExpressJS

Dependencies:

React: 16.7.0
Material Ui Library from Google: v3.9.3
redux: 4.0.1
redux-thunk: 4.0.1
express: 4.17.1
react-jss: 8.6.1
react-router-dom: 4.3.1
react-document-meta: 2.1.2
axios: 0.19.0
@babel/plugin-proposal-class-properties: 7.4.0
@babel/preset-env: 7.4.3
@babel/register: 7.4.4
babel-preset-es2015: 6.24.1

Step1: Create React Application
Create a react app using command create-react-app
Install the create-react-app globally on your machine with below command.

npm install -g create-react-app

Create a project by create-react-app as follows

create-react-app ssr-react-16


Step2: Install necessary npm packages for React server side rendering application
Install the following packages by running the following commands, if necessary please use the same version too.

npm install @material-ui/core
npm install  react-redux
npm install redux
npm install redux-thunk 
npm install express
npm install react-router-dom
npm install react-document-meta
npm install react-jss
npm install axios
npm install @babel/plugin-proposal-class-properties
npm install @babel/preset-env
npm install @babel/register
npm install babel-preset-es2015

Thats it now your app is ready with library setup

Step3: babel configs for react server side app
Create a file called .babelrc in root directory of the app and paste the below code.
Babel is a toolchain that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments. For more you can read the babel doc.

{
  "presets": ["@babel/env", "@babel/preset-react"],
  "plugins": [
    "@babel/plugin-proposal-class-properties"
  ]
}

Step4:
Create a file called www under bin folder which is in root directory
In this file we will be creating a server for client and allocate a port (I am using 5000 here)
Copy the code below to file just created

const app = require('../src/client/src/ssr/clientServer');
const http = require('http');

const port = normalizePort(process.env.PORT || 5000);
app.set('port', port);

const server = http.createServer(app);
server.listen(port);

function normalizePort(val) {
  const port = parseInt(val, 10);
  if (isNaN(port)) {
    // named pipe
    return val;
  }
  if (port >= 0) {
    // port number
    return port;
  }
  return false;
}

In the above code snippet, we are importing a file called clientServer.js that’s covered in the next step.

Step5: ReactJS server side script to initialise server part of client app.
Create a file clientServer.js
For better folder structure, I have organised as shown in the below screenshot where bin and src will falls under root directory. Paste the below code in clientServer file. clientServer is kind of server side script for our client application, it will initiate expressjs and configurations for server side script of client.

require("@babel/register")({
  presets: ["@babel/preset-env"]
});

const express = require('express');
const path = require('path');

const requestHandler = require('./requestHandler');
const app = express();

//static files nd build file reference
app.use(express.static(path.join(__dirname, '../../../../build')));
app.use(express.static(path.join(__dirname, 'public')));

app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'public'));

//for server side rendering
app.use(requestHandler);

// catch 404 and forward to error handler
app.use((req, res, next) => {
  const err = new Error('Notdff Found');
  err.status = 404;
  next(err);
});

module.exports = app;<b><i></i></b>


In the above code you can see a requestHandler file, which is very important file and will see there.

Step6: A request handler for ReactJS for server side rendering and invoking (calling) apis at server side
This step is very important for serving the requested page from server side.  All magic of serving the requested page is done in this script.  When client request for a page, it matches the path and determines whether is there any API call for this page and invokes api then updates HTML body for the respective response. Basically here its creating the react component at server side. Hence React component is fully ready with all the data for the first render itself. 
If there is no api call for a particular page, it just serves a just a static page 


Create a file requestHandler.js Copy the below code.

'use strict';
import React from 'react';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';
import { applyMiddleware, createStore } from 'redux';
import { renderToString } from 'react-dom/server';
import { SheetsRegistry } from 'jss';
import JssProvider from 'react-jss/lib/JssProvider';
import path from 'path'
import fs from 'fs'
import {
  MuiThemeProvider,
  createMuiTheme,
  createGenerateClassName,
} from '@material-ui/core/styles';
import green from '@material-ui/core/colors/green';
import red from '@material-ui/core/colors/red';
import { StaticRouter, matchPath } from 'react-router-dom';
import DocumentMeta from 'react-document-meta';
import reducers from '../reducers/index';
import routes from '../routes';
import routesConfigs from './routesConfig';

const middleware = applyMiddleware(thunk);

function renderView(req, res, state) {

  // Create a theme instance.
  const theme = createMuiTheme({
    palette: {
      primary: green,
      accent: red,
      type: 'light',
    },
  });

  // STEP-1 CREATE A REDUX STORE ON THE SERVER
  const store = createStore(reducers, state, middleware);
  const sheetsRegistry = new SheetsRegistry();
  // Create a sheetsManager instance.
  const sheetsManager = new Map();
  const generateClassName = createGenerateClassName();
  // STEP-2 GET INITIAL STATE FROM THE STORE
  const initialState = JSON.stringify(store.getState()).replace(/&lt;\/script/g, '&lt;\\/script').replace(/&lt;!--/g, '&lt;\\!--');
  // STEP-3 IMPLEMENT REACT-ROUTER ON THE SERVER TO INTERCEPT CLIENT REQUESTs AND DEFINE WHAT TO DO WITH THEM
  const context = {};
  const reactComponent = renderToString(
    &lt;JssProvider registry={sheetsRegistry} generateClassName={generateClassName}&gt;
      &lt;MuiThemeProvider theme={theme} sheetsManager={sheetsManager}&gt;
        &lt;Provider store={store}&gt;
          &lt;StaticRouter
            location={req.url}
            context={context}&gt;
            {routes}
          &lt;/StaticRouter&gt;
        &lt;/Provider&gt;
      &lt;/MuiThemeProvider&gt;
    &lt;/JssProvider&gt;
  );
  const css = sheetsRegistry.toString()
  const reactMetaComponent = DocumentMeta.renderToStaticMarkup();
  if (context.url) {
    // can use the `context.status` that
    // we added in RedirectWithStatus
    redirect(context.status, context.url);
  } else {
    //https://crypt.codemancers.com/posts/2016-09-16-react-server-side-rendering/
    //res.status(200).render('index', { reactComponent, reactMetaComponent, initialState });
    fs.readFile(path.resolve('build/index.html'), 'utf8', (err, data) =&gt; {
      if (err) {
        return res.status(500).send('An error occurred')
      }
      const replacedData = data.replace(
        '&lt;div id="root"&gt;&lt;/div&gt;',
        `&lt;div id="root"&gt;${reactComponent}&lt;/div&gt;
        &lt;style id="jss-server-side"&gt;${css}&lt;/style&gt;
        &lt;script&gt;
          window.INITIAL_STATE = ${initialState}
        &lt;/script&gt;`
      );
      const replacedMetaTagData = replacedData
        .replace(`&lt;meta id="reactMetaTags"/&gt;`,
          `${reactMetaComponent}`);
      res.send(replacedMetaTagData);
    })
  }
}

function handleRender(req, res) {
  const components = routesConfigs
    .filter(route =&gt; matchPath(req.path, route)) // filter matching paths
    .map(route =&gt; route.component); // check if components have data requirement
  let promiseObj = null;
  if (components.length &gt; 0 &amp;&amp; (components[0].fetchData instanceof Function)) {
    /* fetchData is the function defined in each component and make it like class 
       function and it will be called at server side
    */
    components[0]
      .fetchData(req.query)
      .then((response) =&gt; {
        renderView(req, res, response);
      })
      .catch((error) =&gt; {
        console.log('***--- handleRender error ', error);
        renderView(req, res, {});
      });
  } else {
    renderView(req, res, {});
  }
}

module.exports = handleRender;
  1. By default it will be executing a handleRender function in the above code. In the handleRender function, we read a routesConfig file which is just for keeping track of respective component for each route path.
    import LandingComponent from '../pages/landing/components/LandingComponent';
    import AboutComponent from '../pages/about/components/AboutComponent';
    export default [
      {
        path: "/",
        component: LandingComponent,
        exact: true,
      },
      {
        path: '/about',
        component: AboutComponent,
        exact: true,
      }
    ];
  2. routesConfigs will be used by requestHandler to find dynamically which component needs to be rendered for the request. It also checks for fetchData, if fetchData is defined by the component then requestHandler will invoke it which internally invokes api. Note here is all this is happening at server side not on the browser, component object is created in server and fetchData action will be invoked in server. You can see the brief description of fetchData and how to use this in the component in the next step.
  3. When renderView is called, every times it creates is own redux store and a material ui theme provider, thats why we follow this code(which is also mention in the above code snip). 
    const theme = createMuiTheme({
        palette: {
          primary: green,
          accent: red,
          type: 'light',
        },
      });
    
      // STEP-1 CREATE A REDUX STORE ON THE SERVER
      const store = createStore(reducers, state, middleware);
      const sheetsRegistry = new SheetsRegistry();
      // Create a sheetsManager instance.
      const sheetsManager = new Map();
      const generateClassName = createGenerateClassName();
  4. Next major step is reading a build/index.html file which you will get by running npm run build,
    Here we will be injecting the component created at server side into index.html.

    const replacedData = data.replace(
            '&lt;div id="root"&gt;&lt;/div&gt;',
            `&lt;div id="root"&gt;${reactComponent}&lt;/div&gt;
            &lt;style id="jss-server-side"&gt;${css}&lt;/style&gt;
            &lt;script&gt;
              window.INITIAL_STATE = ${initialState}
            &lt;/script&gt;`
     );

    where in index.html of public folder should compulsory has this tag

    &lt;div id="root"&gt;&lt;/div&gt;
  5. For facebook sharing, when you share the url a image and the title and description of the page has to be displayed, for that all those content has to be in the meta tag inside the head tag, hence we need to replaced meta tag with server generated meta tag code. 
    const replacedMetaTagData = replacedData
      .replace(`&lt;meta id="reactMetaTags"/&gt;`,
      `${reactMetaComponent}`);

    Where in index.html of public folder, meta tag with id is should be unchanged

    &lt;meta id="reactMetaTags"/&gt;
  6. Finally we will serve the requested page with updated meta tags and updated html for the first rendering cycle it self. 
    res.send(replacedMetaTagData);
    
    

     

    Step 7

  7. Every component should define an action which will be invoked from server side script, however in server side the request handler will be a generic script and we have to dynamically invoke an action at server side, to achieve that, each component has to define an action and assign action function pointer to fetchData, fetchData is a static class variable kept in component. Check the below code snippet , fetchData is defined at AboutComponent class level and a pointer to action is assigned to it.
    AboutComponent.fetchData = fetchAboutData;
    export default connect(mapStateToProps, null)(AboutComponent);
    
  8. You can refer to the fetchAboutData action in the aboutActions.js which will make the API call to some server, for testing iI am using the JSON placeholder get API which will get the list of posts as response, refer the code below 
    import axios from 'axios';
    export const fetchAboutData = (params) =&gt; {
      return new Promise((resolve, reject) =&gt; {
        const url = 'https://jsonplaceholder.typicode.com/posts';
        axios
          .get(url)
          .then(response =&gt; {
            resolve({
              about: {
                posts: response.data
              }
            });
          })
          .catch((error) =&gt; {
            console.log('Error while fetching posts from network', error);
            reject(null);
          });
      });
    }
  9. In the positive view, it goes to then block(success block) of the axios api call, you can observe that it’s not direct resolve, its resolving a reducer named about and that contain the posts as one of the key, this set up has to be same in both client side reducer as well in axios call in order to use it component (About Component), Observe the below codes, I have shown the code snips of axios call, aboutReducer to mapStateToProps in AboutComponent,
    In axios call 

    resolve({
        about: {
           posts: response.data
        }
    });

    In about reducer 

    const INITIAL_STATE = {
    posts: []
    };

    In about component

    const mapStateToProps = (state) =&gt; {
        return {
           posts:state.about.posts
        };
    }
  10. So in the render method, you can access the posts array like this.props.posts, in the return method of render function i have written one more function which will return the list of posts(only title) and it creates a html code
    getAllPosts = () =&gt; {
       const postView = this.props.posts.map(post =&gt;
       &lt;li&gt;{post.title}&lt;/li&gt;
     );
     return postView;
    }
  11. Once the html is ready, then its in the success block of the fetchData function in the handleRender function of requestHandler file , then followed by the code it calls the renderView method along with data(html) returned from the component.

Step8 :
Update the package.json start script to point to server side rendering beginning of the file, thats www under bin directory. Now server side rendering is really ready. 

  "scripts": {
    "start": "node bin.www",

Step9 : Running project:

  1. In the requestHandler file we will be pointing to index.html inside the build folder, hence we need to generate a build from react by running the command 
    npm run build
  2. Run the start command of your script by
    npm run start

        OR

    nodemon

        OR 

    node bin/www
  3. Since we are running this project on 5000 port, run http://localhost:5000 which is just a page without requesting for API, you simply see as like below
  4. I have made one more component with calling API and printing the results on screen,  run http://localhost:5000/about . I am using an open dummy api for printing list of posts,
    Ie: https://jsonplaceholder.typicode.com/posts

The output picture is shown below

 

An Example Source Code is in Github project Link : https://github.com/pilleanand/ssr-react16/tree/master/ssr-react-16

Posted by:

Anand S,

Software Engineer, Soczen Technologies Pvt Ltd,

Developer: https://sociallygood.com

 

ReactNative 0.59.8 project – unable to archive for for iOS while app store release & Validate Buttons is always grayed out

Recently we faced a very strange issue while releasing our ReactNative App to Apple App Store. We were unable to submit the app to iOS app store because we were failing to generate iOS Archive. XCode always generating Generic XCode Archive rather than iOS App Archive.

Since XCode was generating Generic XCode Archive, Validate button was always disabled ( grayed out). We were failing to proceed further to submit the app. After exploring the issue we came across an apple help page which was suggesting following fixes to be done for our app.

  1. Your archive contains header files.

If your app links against a static library, then your archive contains header files because the library probably uses a Headers build phase to export these files as shown in Figure 4. Headers build phases do not work correctly with static library targets when archiving in Xcode. Delete this phase, add a Copy Files build phase to your library, and use it to export your header files. See Copying Files While Building a Product for more information about adding a Copy File build phase to your project.

 2. Your archive contains static libraries or frameworks.

You must set “Skip Install” to YES to prevent your static libraries or framework from being added to your archive.

the second step was little easy , however the first step was a big headache, a react native app will be having lot of static libraries, in that changing all header build phase to copy files build phase is a big manual work and we will get lot of compilation errors like Redenition of MethodDescriptor in NativeModule.h kind of.

Errors we see after moving header files from headers build phase to copy files build phase

Redefinition of iOS errors

Redefinition of iOS errors

 

Solution : How to release iOS app to app store when archive is troubling in XCode

We have to follow different approach to release the app.

There is another way to upload your app build to the app store: by creating an .ipa file of your app, and uploading it through Application Loader in Xcode ( just click cmd + space in your mac machine and search Application Loader ).

I don’t remember all the resources I found that helped me figure this out, but this was one of them: How to build .ipa application for react-native-ios?

Essentially, after you do the Clean Build Folder, and then Build, you find the .app file in: ~/Library/Developer/Xcode/DerivedData//Build/Products/Release-iphoneos/

Create a new folder on your desktop named Payload (this name is case-sensitive)

Copy your .app file and paste the copy in this Payload folder.

Right click the folder and choose “Compress Payload”

When you save this, do not save it with the .zip extension, but instead save it with a .ipa extension.

This is now your .ipa file for your app, and you can upload this through Xcode Application Loader.

    NOTE: Application loader asks for app specific password , kindly refer to generate app specific password -> https://www.imore.com/how-generate-app-specific-passwords-iphone-ipad-mac

The upload process will tell you if there is anything wrong with your build, but if there is not, it will upload to the app store and you should be able to find it in App Store Connect in a few moments.

Hope this helps you and/or others!

Thanks to Matthew Hall for answering in Stackoverflow -> https://stackoverflow.com/a/57532876/526438

 

ReactJS Source Map : Hiding Source Code From Browser Console

When we deploy React Apps in production environment using npm run build which will generate an optimised production build. The browser shows source code of all the components when we go to Source tab in browser inspector window. In Google chrome browser in you go to Inspector window and enter cntr+p or cmd+p (in mac) you can see all components code.

To hide source code being exposed to outside world just enable GENERATE_SOURCEMAP = false in package.json file as follows

scripts: {
"build": "GENERATE_SOURCEMAP=false react-scripts build"
}

Reference: https://github.com/facebook/create-react-app/issues/4162

 

ReactJS Server Side Rendering : Calling Web Services (APIs) From Server Side

A step by step guide to support server side rendering in reactjs : Calling Web Services (APIs) From Server Side

Before learning how to implement server side rendering in reactjs , let us know why server side rendering ?

Why Server Side Rendering ?

  1. Performance gain for initial page load : Server side rendering improves the performance of initial page load, this is because it reduces number of calls from client to server. Rather than loading empty page first, then call api , get the response then iterate the response to create ui components at client side, for server side rendering, many client-server calls will be removed and for the first render itself the client will get complete HTML with all the data filled. So the browser will just render quickly the final HTML. See the below image taken from Udemy tutorial on ReactJS, which gives complete flow diagram of client-server requires

 

Image Credit – Udemy Server Side Rendering React JS Flow Diagram

2. SEO friendly : Search Engine crawlers will look for server side rendering because it makes sense for crawlers to communicate with your server to get details of your page ?

3. Social Media Sharing: to get the preview of your page when some one share your page in social media like facebook, server side rendering is must, because facebook/twitter/g+ needs og tags to be filled for the first render itself

After knowing importance of server side rendering, let us explore how to enable it using reactjs.

Important Considerations while working on server side rendering

  1. In reactjs if you are dealing with server side rendering, then you should be aware that most of the component life cycle methods will not be called at server side. if you have to do some operations then you should either do it in component’s constructor or componentWillMount 
  2. And you should keep updating redux store from server side as well and give the updated store to client other wise client is unaware of what is changed in the store

How To Enable Server Side Rendering in React : Calling APIs from server side

Prerequisites for server side rendering in reactjs

  1. Having a nodejs middleware for request handling – if your client part is running on 8080 port and api’s are running on 8081 port, then all the requests coming to 8080 port, should go through this middleware. This is where server side api calls will be handled for every route.
  2. We need a Redux Action for API call which will just return a promise – note here is that, this should not dispatch the state, since its called from server side, the dispatch doesn’t make any sense here.
  3. Static function pointer in a component to redux action -> function pointer will be used to call action from server side
  4. Creating redux store at server side to update the data
  5. Keeping a global state and including it in view ( index.ejs or index.pug whichever view engine you use)

Let us see how to implement server side rendering with reactjs

Define request handler middleware in your app.js : this is where we call apis from backend , observe and understand how we call api for respective route. this is common middleware for all routes, but calling right API for respective route is happening due to routesConfig and static function pointer defined in respective component of routes. To understand this completely check how fetchData function is being used in function handleRender(req, res) and NewsDetailComponent

//App.js

// REQUEST HANDLER FOR SERVER-SIDE RENDERING
const requestHandler = require('./requestHandler');
// requestHandler.js

'use strict';

import React from 'react';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { renderToString } from 'react-dom/server';
import { StaticRouter, matchPath } from 'react-router-dom';

//Reducers combiner 
import reducers from '../src/client/reducers/index';

//All the routes defined 
import routes from '../src/routes';

// Routes config which just has path and respective component mapping
import routesConfigs from '../src/routesConfig';


import DocumentMeta from 'react-document-meta';

//A Wrapper for axios where actual api call happens
import { HTTPRequestHandler } from '../src/util/commonRequires';


function renderView(req, res, state) {
    // STEP-1 CREATE A REDUX STORE ON THE SERVER
    const store = createStore(reducers, state);

  // STEP-2 GET INITIAL STATE FROM THE STORE
  const initialState = JSON.stringify(store.getState()).replace(/&lt;\/script/g, '&lt;\\/script').replace(/&lt;!--/g, '&lt;\\!--');
  // STEP-3 IMPLEMENT REACT-ROUTER ON THE SERVER TO INTERCEPT CLIENT REQUESTs AND DEFINE WHAT TO DO WITH THEM
  const context = {};
  const reactComponent = renderToString(
    &lt;Provider store={store}&gt;
      &lt;StaticRouter
        location={req.url}
        context={context}&gt;
        {routes}
      &lt;/StaticRouter&gt;
    &lt;/Provider&gt;
  );
  const reactMetaComponent = DocumentMeta.renderToStaticMarkup();

  if (context.url) {
    // can use the `context.status` that
    // we added in RedirectWithStatus
    redirect(context.status, context.url);
  } else {
    //https://crypt.codemancers.com/posts/2016-09-16-react-server-side-rendering/
    res.status(200).render('index', { reactComponent, reactMetaComponent, initialState });
  }
}
function handleRender(req, res) {
  const components = routesConfigs
    .filter( route =&gt; matchPath( req.path, route ) ) // filter matching paths
    .map( route =&gt; route.component ); // check if components have data requirement
    let promiseObj = null;    
    if (components.length &gt; 0 &amp;&amp; (components[0].fetchData instanceof Function)) {
      components[0]
      .fetchData(req.query)
      .then((response) =&gt; {
        //console.log('***--- response ', response);
          renderView(req, res, response);
      })
      .catch((error) =&gt; {
        console.log('***--- error ', error);
        renderView(req, res, {});
      });
    } else {
      renderView(req, res, {});
    }
}

module.exports = handleRender;

Check the view part and the most important part because this is where the global redux stare is being shared by client and server
// View Part : index.ejs 
// put below lines of code within the &lt;body&gt; tag

&lt;DIV class = 'appStyle' id="app"&gt;&lt;%-reactComponent-%&gt;&lt;/DIV&gt;
&lt;script&gt;window.INITIAL_STATE=&lt;%- initialState -%&gt;&lt;/script&gt;

 

Now let us define a component which embed all the routes

// PrimaryLayout.js

import React from 'react';
import { Route, Switch } from 'react-router-dom';
import DocumentMeta from 'react-document-meta';

import MenuComponent from '../components/common/elements/menu';
import NewsDetailComponent from '../components/pages/NewsDetailComponent';

import {
  NEWS
} from '../../constants';


class PrimaryLayout extends React.Component {
  render() {
    const layoutPath = this.props.match.path;
    return (
      &lt;div style={{ paddingTop: 80 }}&gt;
        &lt;MenuComponent /&gt;
        &lt;main&gt;
          &lt;Switch&gt;
            &lt;Route exact path={layoutPath} component={LandingPageComponent} /&gt;
            &lt;Route exact path={`${layoutPath}${NEWS}/:newsId`} component={NewsDetailComponent} /&gt;
          &lt;/Switch&gt;
        &lt;/main&gt;
      &lt;/div&gt;
    );
  }
}

export default PrimaryLayout;

 

Now let us define all routes

//routes.js

'use strict';
// REACT
import React from 'react';

// REACT-ROUTER
//import {Router, Route, IndexRoute, browserHistory} from 'react-router';
import { Route, Switch } from 'react-router-dom';

import getMuiTheme from 'material-ui/styles/getMuiTheme';
import { MuiThemeProvider } from 'material-ui/styles';

import PrimaryLayout from './client/containers/PrimaryLayout';


// RETRIVES COMPONENTS BASED ON STATUS
const Status = function ({ code, children }) {
  return (
        &lt;Route
          render={function ({ staticContext }) {
            if (staticContext) {
              staticContext.status = code;
            }
            return children;
          }}
        /&gt;
    );
};

//NOT-FOUND COMPONENT
const NotFound = function () {
    return (
      &lt;Status code={404}&gt;
        &lt;div&gt;
          &lt;h2&gt; Sorry, can’t find this page&lt;/h2&gt;
        &lt;/div&gt;
      &lt;/Status&gt;
    );
};

// CLIENT-SERVER SHARED ROUTES
const routes = (
  &lt;MuiThemeProvider muiTheme={getMuiTheme('lightBaseTheme')}&gt;
      &lt;div className='appStyle'&gt;
          {/*
            switch required to handle inclusive rendering,
            example : two different paths like /about /:userName both
            will render both the components switch handles such requests by
            inclusively rendering the specific component
         */}
          &lt;Switch&gt;
            &lt;Route path="/notfound" component={NotFound} /&gt;
            &lt;Route path="/" component={PrimaryLayout} /&gt;
          &lt;/Switch&gt;
      &lt;/div&gt;
    &lt;/MuiThemeProvider&gt;
    );

export default routes;

 

and let us use the routes

// client.js which defines routes 

'use strict';
// REACT
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
// REACT-ROUTER
import { BrowserRouter } from 'react-router-dom';
//import {Router, Route, IndexRoute, browserHistory} from 'react-router';

import { applyMiddleware, createStore } from 'redux';
import logger from 'redux-logger';
import thunk from 'redux-thunk';
import routes from '../routes';


// IMPORT COMBINED REDUCERS
import reducers from './reducers/index';
// STEP 1 create the store
const middleware = applyMiddleware(thunk, logger);
// WE WILL PASS INITIAL STATE FROM SERVER STORE
const initialState = window.INITIAL_STATE;
const store = createStore(reducers, initialState, middleware);

const Routes = (
  &lt;Provider store={store}&gt;
    {/*
      Provider
      Makes the Redux store available to the connect() calls in the component hierarchy below.
      Normally, you can’t use connect() without wrapping a parent or ancestor
      component in
   */}
    {/*
      A &lt;Router&gt; that uses the HTML5 history API (pushState, replaceState and the popstate event)
      to keep your UI in sync with the URL.
    */}
    &lt;BrowserRouter&gt;
      {routes}
    &lt;/BrowserRouter&gt;
  &lt;/Provider&gt;
);

render(
  Routes, document.getElementById('app')
);

 

New Let us define our component

'use strict';
import React from 'react';
import {connect} from 'react-redux';

import { fetchNews, fetchNewsData } from '../actions/newsActions';

 class NewsDetailComponent extends React.Component {
    constructor(props) {
      super(props);
    }
    
    componentDidMount() {
        this.props.fetchNews(this.props.match.params.eventId);
    }
    render() {
        return(
            &lt;div className='container-fluid'&gt;
                &lt;section&gt;
                    &lt;div className='row'&gt;
                        &lt;div className='col-lg-2 col-md-2 col-sm-2 col-xs-1'&gt;&lt;/div&gt;
                        &lt;div className='col-lg-8 col-md-8 col-sm-8 col-xs-10'&gt;
                           {/* here your news component */} 
                        &lt;/div&gt;
                        &lt;div className='col-lg-2 col-md-2 col-sm-2 col-xs-1'&gt;&lt;/div&gt;
                    &lt;/div&gt;
                &lt;/section&gt;
            &lt;/div&gt;
        );
    }
 }


function mapStateToProps(state) {
    return {
        newsInfo: state.newsInfo.newsInfo
    };
}
NewsDetailComponent.fetchData = fetchNewsData;
export default connect(mapStateToProps, {
    fetchNews,
})(NewsDetailComponent);

And redux action which calls API

export const fetchNewsData = (params) =&gt; {
    return new Promise((resolve, reject) =&gt; {
        const newsDetailsUrl = `${NEWS_API_PATH}/${params.newsId}?newsId=${newsId}`;
        HTTPRequestHandler
        .get(newsDetailsUrl)
        .then((apiResponse) =&gt; {
            / * 
                Return the updated state so that we can update redux state 
                from server side
            */
            resolve({
                    news: { 
                        news: { 
                            newsDetails: apiResponse.data.newsDetails,
                        } 
                    }
                  });
            
        })
        .catch((apiError) =&gt; {
            console.log('-- 2 api call fail--- ', apiError);
            reject(null);
        });
    });
}

 

Rather than explaining each line of code written, I would like to help you to understand it by taking your attention on important aspects 

  1. to understand how the redux state is managed from backend and available for front end ( UI component, NewsDetailComponent) check how initialState and window.INITIAL_STATE are being used 
  2. to understand how api is called in a common middleware requestHandler at server side for respective page please check how routesConfig , fetchData, fetchNewsData are being used 
  3. to understand how redux store is managed even at server side and synched with client side which is most important – other wise client is unaware of what happened at server side – check function renderView(req, res, state) (server side) and client.js (client side) both are creating redux store but the data from server is being used by client using a global store object.

References : 

https://medium.freecodecamp.org/demystifying-reacts-server-side-render-de335d408fe4

http://sujinc.com/2018/06/20/all-about-sujinc-com-part-1-reactjs-ssr/

 

React Native Android Exception : App Crashes on Launch

How to check exception ? On crash it just shows Close app dialogue box. To check what is the crash open adb logs and check.

<User_home_directory>/Library/android/sdk/platform-tools/adb logcat

This command shows below exception

Exception : java.lang.RuntimeException: Unable to start activity ComponentInfo{/.MainActivity}: java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation

Fix For this :

Remove android:screenOrientation from your application manifest xml

ReactNative Firebase Application : Firebase App named ‘[DEFAULT]’ already exists (app/duplicate-app)

If by change you are getting following exception 

Firebase App named ‘[DEFAULT]’ already exists (app/duplicate-app)

Then do the following fix :

Check whether firebase is already initialised or not before calling firebase.initializeApp

if (!firebase.apps.length) {
  firebase.initializeApp(firebaseConfig);
}

 

How to Increase Upload Speed for GoogleCloudStorage in nodejs

How to Increase Upload Speed for GoogleCloudStorage in nodejs

Uploading Files to GCP : Google Cloud Storage In Nodejs

const Storage = require('@google-cloud/storage');
const config = require('./gcloudConfig');
const Multer = require('multer');

const CLOUD_BUCKET = config.get('CLOUD_BUCKET');

const storage = Storage({
  projectId: config.get('GCLOUD_PROJECT')
});
const bucket = storage.bucket(CLOUD_BUCKET);

// Returns the public, anonymously accessable URL to a given Cloud Storage
// object.
// The object's ACL has to be set to public read.
// [START public_url]
function getPublicUrl (filename) {
  return `https://storage.googleapis.com/${CLOUD_BUCKET}/${filename}`;
}

// Express middleware that will automatically pass uploads to Cloud Storage.
// req.file is processed and will have two new properties:
// * ``cloudStorageObject`` the object name in cloud storage.
// * ``cloudStoragePublicUrl`` the public url to the object.
// [START process]
function sendUploadToGCS (req, res, next) {
  if (!req.files) {
    return next();
  }
  const data = req.body;
  if (req.files.length === 0) {
    next();
  }
  data.accountNumber = '';
    for (let index = 0; index &lt; req.files.length; index++) {
      const gcsname = `${data.accountNumber}/${Date.now()}${req.files[index].originalname}`;
      const file = bucket.file(gcsname);
      const stream = file.createWriteStream({
        metadata: {
          contentType: req.files[index].mimetype
        },
        resumable: false
      });
      stream.on('error', (err) =&gt; {
        req.files[index].cloudStorageError = err;
        next(err);
      });
    //  console.log(' upload in progress for file ', index);
      stream.on('finish', () =&gt; {
        req.files[index].cloudStorageObject = gcsname;
        file.makePublic().then(() =&gt; {
          req.files[index].cloudStoragePublicUrl = getPublicUrl(gcsname);
          console.log(' upload completed, public url is ', req.files[index].cloudStoragePublicUrl,
                     ' index ', index, ' total count ', req.files.length);
          if (index === (req.files.length - 1)) {
            next();
          }
        });
      });
      stream.end(req.files[index].buffer);
    }
}
// [END process]

// Multer handles parsing multipart/form-data requests.
// This instance is configured to store images in memory.
// This makes it straightforward to upload to Cloud Storage.
// [START multer]

const multer = Multer({
  storage: Multer.MemoryStorage,
  limits: {
    fileSize: 5 * 1024 * 1024 // no larger than 5mb
  }
});
// [END multer]

module.exports = {
  getPublicUrl,
  sendUploadToGCS,
  multer
};

 

The issue is the upload speed is very slow, finding a way to upload faster to google cloud storage

React Native Crash Undefined is not an object (Evaluating ‘Sn[e]’)

React Native Crash Undefined is not an object (Evaluating ‘Sn[e]’)

Any one facing react native build issue? I am trying to generate debug build but its crashing when the app is launched . The exception has no useful information. I was facing the same issue with

sudo react-native run-android

 

But that got resolved after upgrading RN from 0.48 to 0.55(latest Stable Version). But the crash remain same for the apk generated using

sudo gradlew assembleDebug

The crash is similar to https://github.com/facebook/react-native/issues/16745

please see screenshot

ReactNative Undefined Not an object evaluating

ReactNative Undefined Not an object evaluating

Solution: Generating React Native Android Release and Debug Builds

1. If any one facing issue with generating ReactNative android build then do not forget to follow below steps

2. Update your key store details as given here

3. Then explicitly bundle the assets using below command

react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/ 

4. Generate the build using gradle

cd android &amp;&amp; ./gradlew assembleRelease

Note: for release build I am facing another issue as follows

Error in Release build :

FAILURE: Build failed with an exception.

* What went wrong:
Failed to capture snapshot of input files for task ‘bundleReleaseJsAndAssets’ property ‘$1’ during up-to-date check.
> Failed to create MD5 hash for file ‘/Development/SourceCode/MobApp/testApp/root-state/sock’.

* Try:
Run with –stacktrace option to get the stack trace. Run with –info or –debug option to get more log output.

* Get more help at https://help.gradle.org

BUILD FAILED in 2s

To generate debug build

cd android &amp;&amp; ./gradlew assembleDebug

 

Credits : SO Post

Google Assistant makes calls: Google’s New Technology Duplex, makes real time call and close the deal.

Google Assistant makes calls: Google’s New Technology Duplex, makes real time call and close the deal.

Google Assistance Calls - Duplex

Google Assistance Calls – Duplex

 

Google Duplex: An AI System for Accomplishing Real World Tasks Over the Phone

A long-standing goal of human-computer interaction has been to enable people to have a natural conversation with computers, as they would with each other. In recent years, we have witnessed a revolution in the ability of computers to understand and to generate natural speech, especially with the application of deep neural networks (e.g., Google voice searchWaveNet). Still, even with today’s state of the art systems, it is often frustrating having to talk to stilted computerized voices that don’t understand natural language. In particular, automated phone systems are still struggling to recognize simple words and commands. They don’t engage in a conversation flow and force the caller to adjust to the system instead of the system adjusting to the caller.

Reference: GoogleBlogs

React Native react-navigation props.navigation.navigate(“DrawerOpen”) doesn’t work

React Native react-navigation props.navigation.navigate(“DrawerOpen”) doesn’t work

If you are using react-navigation version “1.0.0-beta.11” then the following apis works fine

props.navigation.navigate('DrawerOpen'); // open drawer
props.navigation.navigate('DrawerClose'); // close drawer

 

If you are using react-navigation version “2.0.0-rc.9” then following apis works fine

props.navigation.openDrawer();
props.navigation.closeDrawer();
props.navigation.toggleDrawer();

 

Read More About React-Navigation Package : react-navigation performance issues

Typical React Native Navigation issues people facing for this

navigation.navigate(‘DrawerOpen’) doesn’t work

DrawerToggle not working on Android #2760

Drawer Menu doesn’t work in react-native