Code Sharing Between React Web And React Native

One of the advantages of using React Native is the possibility of sharing code across different devices. This is achievable because under the hood React Native is using the same component which is used on the web.

image1

The difference is only in platform specific UI components. This is why we will reuse the logic of the app. For applying styles I will use styled components which has React Native implementation which will be useful in reusing styles across different platforms.

The starting point is root component which is the same for all platforms:

import React, { Fragment } from 'react';
import ListUsers from './containers/ListUsers';
import CreateUser from './containers/CreateUser';

const App = () => (
  <Fragment>
    <ListUsers />
    <CreateUser />
  </Fragment>
)

export default App;

This component includes 2 containers in which resides our shared logic:

ListUsers:

import React, { Component } from 'react';
import API from '../services/api'
import List from '../components/List';

export default class ListUsers extends Component {
  state = {
    persons: []
  }

  componentDidMount() {
    API.get('users')
      .then(({ data: persons }) => this.setState({ persons }));
  }

  render() {
    const { persons } = this.state;
    return <List data={persons} />;
  }
}

CreateUser:

import React, { Component, Fragment } from 'react';
import { pathOr } from 'ramda';
import API from '../services/api'
import Input from '../components/Input';
import Button from '../components/Button';

export default class CreateUser extends Component {
  state = {
    name: '',
  }

  handleChange = event => {
    const name = pathOr(event, ['target', 'value'])(event);
    this.setState({ name });
  }

  handleSubmit = () => {
    const { name: user } = this.state;

    API.post('users', { user })
      .then(res => console.log(res.data));
  }

  render() {
    const { name } = this.state;
    return (
      <Fragment>
        <Input value={name} handleChange={this.handleChange} />
        <Button onAction={this.handleSubmit} title="Create user" />
      </Fragment>
    )
  }
}

All the magic is happening when we are importing components:

import List from '../components/List';

List is a folder with different extensions .js, .ios.js and .android.js. Depending on which platform we want to execute our app, corresponding file will be loaded. .js will be loaded for the web version, the rest will be loaded according to platform extension, more details here.

And, lastly we will reuse styles, by creating a common styles file:

import { css } from 'styled-components';

const styles = css`
 background-color: red;
`
export default styles;

Then we will wrap platform specific element/ component.

For web:


import React from 'react';
import styled from 'styled-components';
import styles from './styles';

const Button = styled.button`${styles}`;

const ButtonItem = ({ title, onAction }) => (
 <Button onClick={onAction}>
 {title}
 </Button>
)

export default ButtonItem;

And for mobile:

import React from 'react';
import { Button } from 'react-native';
import styled from 'styled-components/native';
import styles from './styles';

const StyledView = styled.View`${styles}`;

const ButtonItem = ({ onAction, title = 'Button' }) => (
  <StyledView>
    <Button
      onPress={onAction}
      title={title}
      accessibilityLabel={title}
    />
  </StyledView>
);

export default ButtonItem;

Here is the repo with all code. Further I will investigate how it’s possible to reuse react code also on desktop platform.

See examples of exceptional work we have done for our clients

View case studies

GET IN TOUCH

Contact us to discuss your next project:

+44 (0) 20 8090 0828
info@atomate.net

Contact us now