REACT NATIVE WITH REDUX

Redux is a neat library that manages storage of a React or React Native application.

It has a global store which is a “single source of truth”, but also allows you to separate data logic with reducer composition.

Redux really shines when your application gets complicated with many fragmented data states. Redux keeps everything organised and helps you stay sane when handling increasingly complicated front-end requirements in React and React Native.

This post assumes that you have knowledge with React Native and Redux and want to combine these two awesome libraries together for your cool project.

We will implement a simple app that gets user’s input and displays the result of that action.

Here is a demonstration animation:

alt text

Barebone React Native project

Run this command

react-native init React NativeRedux

This will create a project structure like this

.
├── android
├── index.android.js
├── index.ios.js
├── ios
├── node_modules
└── package.json

index.ios.js and index.android.js are the entry files for iOS and Android accordingly.

// index.ios.js

import React, { Component } from 'react'
import { AppRegistry } from 'react-native'

export default class React NativeRedux extends Component {
  render() {
    return (
      // ...
    )
  }
}

AppRegistry.registerComponent('React NativeRedux', () => React NativeRedux)

Install redux

We need two separate libraries redux and react-redux to make it work. Run this command to install

yarn add redux react-redux

So we use yarn to add the redux library to the project. You are probably wondering what react-redux is doing here.

react-redux is the library that enables react bindings in redux. It provides Provider component and connect function:

  • Provider makes the global store available to all of the children containers or components
  • connect links the react component to the redux store, it makes utility functions like dispatch and getState() available. It also does some sort of optimisation to prevent unnecessary rendering.

In redux, we will use two separate components: presentational and containers. The presentational component renders the UI, and the container component works with the data and actions.

I am going to group the files by functionalities using this folder structure:

src
├── actions
├── components
├── containers
├── reducers
└── store

Glue React and Redux

Store

First we need to configure the store. It requires the root reducer; we will implement it later. Right now this is all that we need to feed the Provider:

// src/stores/index.js

import { createStore } from 'redux'
import rootReducer from '../reducers'

export default createStore(rootReducer)

Root component

We need a root component that connects to redux’s store. We need to wrap up the main App component inside of the Provider to the store is available.

// src/Root.js

import React, { Component } from 'react'
import { Provider } from 'react-redux'
import configureStore from './store'
import App from './containers/App'

const store = configureStore()

export default class Root extends Component {
  render () {
    return (
      <Provider store={store}>
        <App />
      </Provider>
    )
  }
}

Presentational Component

We use the “pure” component to handle the rendering, it takes whatever in the props and shows to the UI. This is where we design the app layout with View, Button, Text, StyleSheet…

// src/components/RedPillBluePill.js

import React from 'react'
import {
  View,
  TouchableOpacity,
  Text,
  StyleSheet
} from 'react-native'

export default ({ choose, result }) => (
  <View style={ styles.container }>
    <View style={ styles.buttons }>
      <TouchableOpacity style={ styles.red } onPress={ () => choose('red') } >
        <Text>Red</Text>
      </TouchableOpacity>

      <TouchableOpacity style={ styles.blue } onPress={ () => choose('blue') } >
        <Text>Blue</Text>
      </TouchableOpacity>
    </View>

    <Text>{ result }</Text>
  </View>
)

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  buttons: {
    flexDirection: 'row',
    marginBottom: 20
  },
  red: {
    paddingVertical: 10,
    paddingHorizontal: 20,
    backgroundColor: 'red'
  },
  blue: {
    paddingVertical: 10,
    paddingHorizontal: 20,
    backgroundColor: 'blue'
  }
})

Container Component

This connects the presentational component to the store. It prepares the data and defines action handler before passing to the presentational component as props. It has access to state and dispatch to connect with Redux’s store. We will pass the choose action handler and result message to the other component.

// src/containers/App.js

import { connect } from 'react-redux'
import RedPillBluePill from '../components/RedPillBluePill'
import { choose } from '../actions'

export default connect(
  state => ({
    result: state.result
  }),
  dispatch => ({
    choose: pill => dispatch(choose(pill))
  })
)(RedPillBluePill)

Handling actions

Actions are triggered via dispatch; it returns the payload which in turn sent to the store.

// src/actions/index.js

export const choose = pill => {
  return {
    type: 'CHOOSE_PILL',
    pill: pill
  }
}

Actions do not change the data or anything. It just “forwards” the payload to the reducers.

Reducers

Redux store is “single source of truth”, meaning all of the app’s data is there. You can however use reducer composition to separate the logic. In this app, we just need one reducer to handle the CHOOSE_PILL action and compute the result message.

// src/reducers/index.js

import { combineReducers } from 'redux'

const result = (state = 'Choose wisely', action) => {
  switch (action.type) {
    case 'CHOOSE_PILL':
      if (action.pill === 'red') {
        return 'Welcome to the real world'
      } else {
        return 'Stay in the Matrix'
      }
    default:
      return state
  }
}
const reducer = combineReducers({ result })
export default reducer

That is basically everything we need for this simple demo. It shows you the core concept of redux and how to make it work with React Native. To note; real React Native apps however needs a much more complicated reducer composition and sophisticated data transformation in the store.

Conclusion

Redux is a really simple library to help you manage the app’s store. I like the “single source of truth” principle, it makes thing more predictable.

At first you may find following the unidirectional data flow in redux is pretty strict, but after a while, you will find it comfortable to work with, and coding and debugging will become more natural and even enjoyable.

The project is available at a public GitHub repo:

Redux-React Native

Khac Anh is a full-stack engineer with an extensive background in web and mobile development. He has built and lead tech teams in several outsourcing and startup companies, one of which was successfully publicly listed.
You might also like...
To stay productive in programming you need to receive feedback for your code as fast as possible. For example, when you want to test out some styling effects with CSS...
Basically it's where you deploy your code to. Using a PaaS has several benefits over Infrastructure-as-a-Service (IaaS) or setting your own physical servers...
React Native provides its own version of ListView, it is essentially different from Android's ListView or iOS'es UITableView...
contact codelink

Contact

Let us know how we can help!