Building of react-native-web & tricks

T. Emre Yildirim
Innovance Blog
Published in
4 min readDec 20, 2019

In this story, I would like to write about react-native-web library. It is an amazing tool that is really and really helpful for “write once run anywhere” and we also use it in a professional banking app…

Firstly, I would like to show a simple react-native-web project on Github: https://github.com/temreyildirim8/react-native-for-web which I will explain in this story step by step. Then I will try to give some tricks about react-native-web development after understanding construction.

Let’s move on with the building of the project. There are some approaches for the construction of react-native-web, I will explain my way… We need to locate the folder that we wanna build our project, then write below ones:

react-native init reactNativeWeb // to create projectnpm i react react-dom react-native-web react-redux redux redux-thunk --save // librariesnpm i webpack babel-loader babel-preset-react babel-preset-es2015 --save // configuring libraries

After that, copy the default App.js to somewhere else and refactor defaultApp.js so that it simply imports and renders the src/App.js that you just created:

// App.jsimport React from 'react';
import HybridApp from './src/App';
const App = (props) => {
return (
<HybridApp />
);
}
export default App;

Create a folder called src and copy default App.js into src/App.js :

// src/App.jsimport React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
android:
'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});
export default class App extends Component {render() {return (<View style={styles.container}><Text style={styles.welcome}>Welcome to React Native!</Text><Text style={styles.instructions}>To get started, edit App.js</Text><Text style={styles.instructions}>{instructions}</Text></View>);}}// I deleted styles from here, you can reach it at the project on github or from default App.js of your default project

And create src/index.js :

// src/index.jsimport React from ‘react’;
import ReactDom from ‘react-dom’;
import App from ‘./App’;
ReactDom.render(<App />, document.getElementById(“root”));

Create a folder called public and create public/index.html for web render.

<!-- public/index.html --><!DOCTYPE html><html><head><meta charset="utf-8" /><title>RN For Web App</title></head><body><div id="root"></div></body></html></html>

And we need to add below scripts to package.json in order to build and start platforms differently:

// package.json"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start", // it already exists
"start-web": "react-scripts start",
"build-web": "react-scripts build"
// And you can write different scripts to run ios and android here},

After we arrange scripts, we need to specify routes and add redux to our project.

Create routes under /src and create paths, Routes.web.js, Routes.native.js under routes:

// src/routes/paths.jsexport default {
DEFAULT: ‘/’,
DASHBOARD: ‘/dashboard’,
RESULTS: ‘/results’
}
// src/routes/Routes.web.jsimport React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import paths from './paths';
import Dashboard from '../screens/Dashboard/Dashboard';
import Results from '../screens/Results/Results';
const Routes = () => (<Router><Switch><Route exact path={paths.DEFAULT} component={Dashboard} /><Route path={paths.RESULTS} component={Results} /></Switch></Router>);export default Routes;
// src/routes/Routes.native.jsimport React from "react";
import { NativeRouter as Router, Route, Switch } from "react-router-native";
import paths from './paths';
import Dashboard from '../screens/Dashboard/Dashboard';
import Results from '../screens/Results/Results';
const Routes = () => (<Router><Switch><Route exact path={paths.DEFAULT} component={Dashboard} /><Route path={paths.RESULTS} component={Results} /></Switch></Router>);export default Routes;

Create store under /src and create actions, generics, reducers under store, you can look at the Github link for them. (I don't give details about redux connection here, it is not our subject now) Finally, we will write/src/App.js file and it should look like that:

// src/App.jsimport React, {Component} from 'react';
import { Provider } from 'react-redux';
import { createStore, combineReducers, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import Routes from './routes/Routes';
import dashboardReducer from './store/reducers/dashboardReducer'
// Combine all reducers
const rootReducer = combineReducers({
dashboard: dashboardReducer
});
// Logger for dispatching, console.logs are optional
const logger = state => {
return next => {return action => {console.log("Middleware dispatching", action);const result = next(action);console.log("[MiddleWare next state]", state.getState());return result;};};};// Redux dev tools
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
// Store instance
const store = createStore(rootReducer, composeEnhancers(applyMiddleware(logger, thunk)));
export default class App extends Component {render() {return (<Provider store={store}><Routes /></Provider>);}}

We need to write npm run start-webon the console to start our project on browser at localhost:3000 and if it looks like below, it is done: congrats!

the output of our first project

Secondly, I want to talk about some tricks about react-native-web:

We need to learn react-native equivalents of web tags:

View for <div> and WebView for <iframe>
Text for <span>
Image for <img />
TouchableHighlight for <button>
ScrollView for <div style=”overflow: auto”>

We can differentiate codes according to platforms like above part: Routes.web.js and Routes.native.js

Be careful about defining styles!!

View — width, height, margin, padding, background, border, opacity
Layout — flex(most dangerous for web), position(absolute, relative) and transform
Text — color, font, lineHeight, textAlign, textShadow

p.s: if you seperate your files as .web.js, you can use web tags like <div> in it

You cannot use these native-only tags on web:

Navigator
ListView
ActivityIndicatorIOS
SegmentedControlIOS
RefreshControl
TabBarIOS

etc…

Sometimes, you may need to separate your code pieces (especially on forms) for different platforms. E.g select, dropdown, etc. components for web…

If you have questions, suggestions or any other issue, do not hesitate to write a response or contact me. 🙋‍♂️

--

--