SHARING CODE BETWEEN REACT AND RECT-NATIVE

GOOD, BAD &UNSHARABLE

bene@theodo.co.uk
Ben Ellerby
First React-Native London Meetup
July 28, 2016​

Types of Code

UI Render

Business Logic

Configuration

ui rENDER coDE

UI Render

  • Different render environments (<div> != <View>)
  • React-Native-Web (no longer supported by Twitter and SSR issues)
  • ReactXP (SSR issues and have not seen a project using it successfully)
  • styled-components/universal (Same SSR issues as React-Native-Web and too experimental)

Styled-components

UI Render

Visual primitives for the component age.

const Button = styled.button`
  border-radius: 3px;
  padding: 0.25em 1em;
  margin: 0 1em;
  background: transparent;
  color: palevioletred;
  border: 2px solid palevioletred;
`;

Really helpful in React, but not always chosen for React-Native project

(I'm a fan, even if tagged template literals get some getting used to)

Styled-components

/universal

UI Render

Styled-components

/universal

UI Render

Builds off React-Primitives

"Primative React Interfaces Across Targets"

  • Animated
  • StyleSheet
  • View.
  • Text
  • Image
  • Touchable
  • Easing
  • Dimensions
  • PixelRatio
  • Platform:(iOS, Android, Web, Sketch, VR,...)
  • TextInput

https://github.com/lelandrichardson/react-primitives

Styled-components

/universal

UI Render

Styled-components

/universal

UI Render

Sketch

React

React-Native

Styled-components

/universal

UI Render

Note that this is an experimental release: There might be bugs and there also isn’t a massive amount of documentation

ui rENDER coDE

UI Render

I believe that Web, Mobile Web and Native Application environments all require a specific design and user experience.

Types of Code

UI Render

Business Logic

Configuration

API / Formatting

Types of Code

API / Formatting

API calls, authentication and formatting of request & response data.

Types of Code

Configuration

Config files, translation files and most constant data is not render environment specific.

 

If I update a translation on my app, it's likely I want that changed rolled out on my site too.

Types of Code

Business Logic

Again environment independent.

 

If a user can only add 20 items to their basket, this rule will hold true in web and native equally.

Types of Code

UI Render

Business Logic

Configuration

API / Formatting

State Management & Data

+

State Management & Data

+

  • modal open
  • translations
  • analytic event firing...
  • product data
  • search
  • pagination...

State Management & Data

UI

Render Environment Independent

Our whole redux store is shared

Our Apollo queries are shared 

Higher Order Components

A higher-order component (HOC) is an advanced technique in React for reusing component logic. HOCs are not part of the React API, per se. They are a pattern that emerges from React’s compositional nature.

Higher Order Components: Apollo

// @flow
import React from 'react';
import { Query } from 'react-apollo';

const withData = (query, backupData) => WrappedComponent => {
  return props => (
    <Query query={query} pollInterval={10000}>
      {injectedProps => <WrappedComponent backupData={backupData} {...injectedProps} {...props} />};
    </Query>
  );
};

export default withData;

Higher Order Components: Apollo

All Apollo query HOCs are shared:

 

e.g. withSearchResults, withBasket, withProducts

APPROACH To Sharing

MadeNative

MadeWeb

MadeShared

APPROACH To Sharing

MadeShared

   /hoc
      /queries
      /conditional-render...
   /dataFormatting
   /config
      /translations
      /colours
   /types
   /api
   /redux
      /actions
      /reducers
      /selectors

APPROACH To Sharing

import React from 'react';
import { connect } from 'react-redux';
import { compose, branch, renderComponent } from 'recompose';
import { getUserPermissionSets } from 'redux/login/login.selectors';

const mapStateToProps = state => ({
  userPermissions: getUserPermissionSets(state),
});

export default (permission, UnauthorisedComponent) =>
  compose(
    connect(mapStateToProps),
    branch(
      ({ userPermissions }) => !userPermissions.includes(permission),
      renderComponent(UnauthorisedComponent),
    ),
  );
renderIfAuthorised(permissionsMap.CREATE_ROLE)(
  RoleCreationPageWrapper,
);

APPROACH To Sharing

MadeShared

var path = require('path');
module.exports = {
  entry: './shared/index.js',
  output: {
    path: path.resolve(__dirname),
    filename: 'index.js',
    libraryTarget: 'commonjs2',
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        include: path.resolve(__dirname, 'shared'),
        exclude: /(node_modules|bower_components|build)\//,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['env'],
          },
        },
      },
    ],
  },
  externals: {
    react: 'commonjs react',
    'react-apollo': 'commonjs react-apollo',
  },
};

Webpack config to transpile to commonjs2

APPROACH To Sharing

...
  "dependencies": {
    ...
    "made-shared":
      "git+https://AUTHTOKEN:x-oauth-basic@github.com/REPO/made-shared.git#master-1.05",
    ...
...

MadeWeb / MadeNative

  • Using basic x-auth tokens of a 'bot' user with read-only access
  • Using git tags as versions (#BRANCH-VERSION)
  • `yarn link` for local dev

APPROACH To Sharing

...
  "dependencies": {
    ...
    "made-shared":
      "git+https://AUTHTOKEN:x-oauth-basic@github.com/REPO/made-shared.git#master-1.05",
    ...
...

MadeWeb / MadeNative

 

yarn build

git tag master-1.06

git push --tags

git merge

Update package.json

APPROACH To Sharing

MadeWeb / MadeNative

...
  "dependencies": {
    ...
    "made-shared": "1.05",
    ...
...

App Center!

MadeNative

We use AppCenter as our App CI

 

It needs to pull the shared library, but it's private...

App Center!

MadeNative

Me: Hello, we’re wanting to have a shared library used in our project. This would require an npm install from a private NPM repo (through package cloud). What is the best practice for adding a private npm access on the AppCenter CI?

App Center!

MadeNative

Microsoft: We currently only support cloud git repositories hosted on VSTS, Bitbucket and GitHub. Support for private repos is not available yet but we are building new features all the time, you can keep an eye out on our roadmap for upcoming features.

App Center!

MadeNative

Conclusion

  • Code sharing is a great advantage of React & React-Native
  • Share your non-design render code.
  • Your app and web app should have a different UX
  • HOCs help share component logic
  • Publishing a private npm package creates a good workflow

Thanks, MADE.COM

bene@theodo.co.uk

ben@ellerby.tech

https://www.linkedin.com/in/benjaminellerby/

Sharing Code Between React and React-Native: The Good, The Bad and the Unsharable

By Ben Ellerby

Sharing Code Between React and React-Native: The Good, The Bad and the Unsharable

Talk given at the React-Native-London meetup.

  • 815