This site runs best with JavaScript enabled.

Code Sharing Between React Web And React Native

Software Engineer, React Training, Testing JavaScript Training

One of the advantages of using React Native is the possibility of sharing code across different devices.

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. alt text

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:

1import React, {Fragment} from 'react'
2import ListUsers from './containers/ListUsers'
3import CreateUser from './containers/CreateUser'
4
5const App = () => (
6 <Fragment>
7 <ListUsers />
8 <CreateUser />
9 </Fragment>
10)
11
12export default App

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

ListUsers :

1import React, {Component} from 'react'
2import API from '../services/api'
3import List from '../components/List'
4
5export default class ListUsers extends Component {
6 state = {
7 persons: [],
8 }
9
10 componentDidMount() {
11 API.get('users').then(({data: persons}) => this.setState({persons}))
12 }
13
14 render() {
15 const {persons} = this.state
16 return <List data={persons} />
17 }
18}

CreateUser :

1import React, {Component, Fragment} from 'react'
2import {pathOr} from 'ramda'
3import API from '../services/api'
4import Input from '../components/Input'
5import Button from '../components/Button'
6
7export default class CreateUser extends Component {
8 state = {
9 name: '',
10 }
11
12 handleChange = event => {
13 const name = pathOr(event, ['target', 'value'])(event)
14 this.setState({name})
15 }
16
17 handleSubmit = () => {
18 const {name: user} = this.state
19
20 API.post('users', {user}).then(res => console.log(res.data))
21 }
22
23 render() {
24 const {name} = this.state
25 return (
26 <Fragment>
27 <Input value={name} handleChange={this.handleChange} />
28 <Button onAction={this.handleSubmit} title="Create user" />
29 </Fragment>
30 )
31 }
32}

All the magic is happening when we are importing components:

1import 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:

1import {css} from 'styled-components'
2
3const styles = css`
4 background-color: red;
5`
6export default styles

Then we will wrap platform specific element/ component.

For web:

1import React from 'react'
2import styled from 'styled-components'
3import styles from './styles'
4
5const Button = styled.button`
6 ${styles}
7`
8
9const ButtonItem = ({title, onAction}) => (
10 <Button onClick={onAction}>{title}</Button>
11)
12
13export default ButtonItem

And for mobile:

1import React from 'react'
2import {Button} from 'react-native'
3import styled from 'styled-components/native'
4import styles from './styles'
5
6const StyledView = styled.View`
7 ${styles}
8`
9
10const ButtonItem = ({onAction, title = 'Button'}) => (
11 <StyledView>
12 <Button onPress={onAction} title={title} accessibilityLabel={title} />
13 </StyledView>
14)
15
16export 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.

Vadim Nicolai

Vadim Nicolai is a JavaScript software engineer.