React Native Redux and REST API example

Install expo cli if it’s not yet installed.

npm install -g expo-cli

Initialize a project.

expo init reactNativeReduxRestApiExampleGithub

Install dependencies to the project.

yarn add redux react-redux redux-thunk

App.js, the top level class that glues everything together.

import React, { Component } from 'react';
import { StyleSheet, View } from 'react-native';
import { Provider } from 'react-redux';
import { applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
import GitAccount from './GitAccount';
import { accountReducer, initialState } from './reducer';

console.log(`${Date()} 1111111111>>> initialization of Redux for the application.`);
const rootReducer = accountReducer;
const middlewares = [thunk];
const store = createStore(rootReducer, initialState, applyMiddleware(...middlewares));

export default class App extends Component {
  render() {
    console.log(`${Date()} 2222222222>>> Provider is a wrapper to the application and responsible for providing access to the created store`);
    return (
      
        
          
        
      
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    marginTop: 50
  }
});

GitAccount.js, the view class for triggering an action and displaying the result.

import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import fetchAccount from './fetchAccount';
import { getAccountError, getAccountLoading, getAccountSuccess } from './reducer';

class GitAccount extends Component {
  componentDidMount() {
    console.log(`${Date()} 5555555555>>> componentDidMount props: ` + JSON.stringify(this.props));
    console.log(`${Date()} 5555555555>>> componentDidMount state: ` + JSON.stringify(this.state));
    console.log(`${Date()} 5555555555>>> componentDidMount initiates the api call fetchAccount.`);
    this.props.fetchAccount('google');
  }
  render() {
    console.log(`${Date()} 4444444444>>> render props: ` + JSON.stringify(this.props));
    console.log(`${Date()} 4444444444>>> render state: ` + JSON.stringify(this.state));
    const { account } = this.props;
    return (
      
        {JSON.stringify(account)}
      
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    margin: 16,
  }
});

// Map the state of the redux store to the component props.
const mapStateToProps = state => {
  console.log(`${Date()} 3333333333>>> mapStateToProps state: ` + JSON.stringify(state));
  return {
    loading: getAccountLoading(state),
    account: getAccountSuccess(state),
    error: getAccountError(state),
  };
};

// Map the dispatched actions to the component props.
// This makes the function call 'this.props.accountInfo('google')' in componentDidMount possible.
const mapDispatchToProps = dispatch => bindActionCreators({
  fetchAccount: fetchAccount
}, dispatch)

// currying function https://blog.benestudio.co/currying-in-javascript-es6-540d2ad09400
export default connect(mapStateToProps, mapDispatchToProps)(GitAccount);

fetchAccount.js, making the api call and dispatch actions for loading, success and error.

import { fetchAccountError, fetchAccountLoading, fetchAccountSuccess } from './actions';

export default function fetchAccount(accountId) {
    return dispatch => {

        dispatch(fetchAccountLoading());

        fetch(`https://api.github.com/users/${accountId}`)
        .then(res => res.json())
        .then(res => {
            console.log(`${Date()} 6666666666>>> fetch account api raw result: ` + JSON.stringify(res));
            if (res.error) {
                throw(res.error);
            }

            dispatch(fetchAccountSuccess(res));

            return res;
        })
        .catch(error => {
            dispatch(fetchAccountError(error));
        })
    }
}

actions.js, the defined actions.

export const FETCH_ACCOUNT_LOADING = 'FETCH_ACCOUNT_LOADING';
export const FETCH_ACCOUNT_SUCCESS = 'FETCH_ACCOUNT_SUCCESS';
export const FETCH_ACCOUNT_ERROR = 'FETCH_ACCOUNT_ERROR';

export function fetchAccountLoading() {
    return {
        type: FETCH_ACCOUNT_LOADING
    }
}

export function fetchAccountSuccess(account) {
    console.log(`${Date()} 7777777777>>> fetchAccountSuccess account: ` + JSON.stringify(account));
    return {
        type: FETCH_ACCOUNT_SUCCESS,
        payload: account
    }
}

export function fetchAccountError(error) {
    return {
        type: FETCH_ACCOUNT_ERROR,
        error: error
    }
}

reducer.js, receives actions, makes adjustments to the actions and the adjusted actions will be emitted to the view layer.

import { FETCH_ACCOUNT_ERROR, FETCH_ACCOUNT_LOADING, FETCH_ACCOUNT_SUCCESS } from './actions';

export const initialState = {
    loading: false,
    account: [],
    error: null
}

function selectInterestedAccountInfo(account) {
    return Object.keys(account).reduce(function(obj, k) {
        if (["login", "url", "name", "created_at", "bio", "email", "public_repos"].includes(k)) {
            obj[k] = account[k];
        }
        return obj;
      }, {});
}

export function accountReducer(state = initialState, action) {
    switch(action.type) {
        case FETCH_ACCOUNT_LOADING:
            return {
                ...state,
                loading: true
            }
        case FETCH_ACCOUNT_SUCCESS:
            return {
                ...state,
                loading: false,
                account: selectInterestedAccountInfo(action.payload)
            }
        case FETCH_ACCOUNT_ERROR:
            return {
                ...state,
                loading: false,
                error: action.error
            }
        default:
            return state;
    }
}

export const getAccountSuccess = state => state.account;
export const getAccountLoading = state => state.loading;
export const getAccountError = state => state.error;

debug logs:

Sun Feb 16 2020 23:36:12 GMT-0800 (Pacific Standard Time) 1111111111>>> initialization of Redux for the application.
RCTLog.js:47 Running application reactNativeReduxExample ({
    initialProps =     {
    };
    rootTag = 371;
})
infoLog.js:16 Running "reactNativeReduxExample" with {"rootTag":371,"initialProps":{}}
/Applications/React Native Debugger.app/Contents/Resources/app.asar/node_modules/react-devtools-core/build/standalone.js:3 [React DevTools] Connected
App.js:16 Sun Feb 16 2020 23:36:12 GMT-0800 (Pacific Standard Time) 2222222222>>> Provider is a wrapper to the application and responsible for providing access to the created store
GitAccount.js:36 Sun Feb 16 2020 23:36:12 GMT-0800 (Pacific Standard Time) 3333333333>>> mapStateToProps state: {"loading":false,"account":[],"error":null}
GitAccount.js:16 Sun Feb 16 2020 23:36:12 GMT-0800 (Pacific Standard Time) 4444444444>>> render props: {"loading":false,"account":[],"error":null}
GitAccount.js:17 Sun Feb 16 2020 23:36:12 GMT-0800 (Pacific Standard Time) 4444444444>>> render state: null
GitAccount.js:10 Sun Feb 16 2020 23:36:12 GMT-0800 (Pacific Standard Time) 5555555555>>> componentDidMount props: {"loading":false,"account":[],"error":null}
GitAccount.js:11 Sun Feb 16 2020 23:36:12 GMT-0800 (Pacific Standard Time) 5555555555>>> componentDidMount state: null
GitAccount.js:12 Sun Feb 16 2020 23:36:12 GMT-0800 (Pacific Standard Time) 5555555555>>> componentDidMount initiates the api call fetchAccount.
GitAccount.js:36 Sun Feb 16 2020 23:36:12 GMT-0800 (Pacific Standard Time) 3333333333>>> mapStateToProps state: {"loading":true,"account":[],"error":null}
GitAccount.js:16 Sun Feb 16 2020 23:36:12 GMT-0800 (Pacific Standard Time) 4444444444>>> render props: {"loading":true,"account":[],"error":null}
GitAccount.js:17 Sun Feb 16 2020 23:36:12 GMT-0800 (Pacific Standard Time) 4444444444>>> render state: null
fetchAccount.js:11 Sun Feb 16 2020 23:36:13 GMT-0800 (Pacific Standard Time) 6666666666>>> fetch account api raw result: {"login":"google","id":1342004,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEzNDIwMDQ=","avatar_url":"https://avatars1.githubusercontent.com/u/1342004?v=4","gravatar_id":"","url":"https://api.github.com/users/google","html_url":"https://github.com/google","followers_url":"https://api.github.com/users/google/followers","following_url":"https://api.github.com/users/google/following{/other_user}","gists_url":"https://api.github.com/users/google/gists{/gist_id}","starred_url":"https://api.github.com/users/google/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/google/subscriptions","organizations_url":"https://api.github.com/users/google/orgs","repos_url":"https://api.github.com/users/google/repos","events_url":"https://api.github.com/users/google/events{/privacy}","received_events_url":"https://api.github.com/users/google/received_events","type":"Organization","site_admin":false,"name":"Google","company":null,"blog":"https://opensource.google/","location":null,"email":"opensource@google.com","hireable":null,"bio":"Google ❤️ Open Source","public_repos":1669,"public_gists":0,"followers":0,"following":0,"created_at":"2012-01-18T01:30:18Z","updated_at":"2019-12-19T21:09:14Z"}
actions.js:12 Sun Feb 16 2020 23:36:13 GMT-0800 (Pacific Standard Time) 7777777777>>> fetchAccountSuccess account: {"login":"google","id":1342004,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEzNDIwMDQ=","avatar_url":"https://avatars1.githubusercontent.com/u/1342004?v=4","gravatar_id":"","url":"https://api.github.com/users/google","html_url":"https://github.com/google","followers_url":"https://api.github.com/users/google/followers","following_url":"https://api.github.com/users/google/following{/other_user}","gists_url":"https://api.github.com/users/google/gists{/gist_id}","starred_url":"https://api.github.com/users/google/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/google/subscriptions","organizations_url":"https://api.github.com/users/google/orgs","repos_url":"https://api.github.com/users/google/repos","events_url":"https://api.github.com/users/google/events{/privacy}","received_events_url":"https://api.github.com/users/google/received_events","type":"Organization","site_admin":false,"name":"Google","company":null,"blog":"https://opensource.google/","location":null,"email":"opensource@google.com","hireable":null,"bio":"Google ❤️ Open Source","public_repos":1669,"public_gists":0,"followers":0,"following":0,"created_at":"2012-01-18T01:30:18Z","updated_at":"2019-12-19T21:09:14Z"}
GitAccount.js:36 Sun Feb 16 2020 23:36:13 GMT-0800 (Pacific Standard Time) 3333333333>>> mapStateToProps state: {"loading":false,"account":{"login":"google","url":"https://api.github.com/users/google","name":"Google","email":"opensource@google.com","bio":"Google ❤️ Open Source","public_repos":1669,"created_at":"2012-01-18T01:30:18Z"},"error":null}
GitAccount.js:16 Sun Feb 16 2020 23:36:13 GMT-0800 (Pacific Standard Time) 4444444444>>> render props: {"loading":false,"account":{"login":"google","url":"https://api.github.com/users/google","name":"Google","email":"opensource@google.com","bio":"Google ❤️ Open Source","public_repos":1669,"created_at":"2012-01-18T01:30:18Z"},"error":null}
GitAccount.js:17 Sun Feb 16 2020 23:36:13 GMT-0800 (Pacific Standard Time) 4444444444>>> render state: null

Complete example in Github

Search within Codexpedia

Custom Search

Search the entire web

Custom Search