Redux is a predictable state container for JavaScript app
actions
function getData() {
  return {
    type: FETCHING_DATA
  }
}
function getDataSuccess(data) {
  return {
    type: FETCHING_DATA_SUCCESS,
    data,
  }
}
function getDataFailure() {
  return {
    type: FETCHING_DATA_FAILUR
  }
}reducers
const initialState = {
  data: [],
  dataFetched: false,
  isFetching: false,
  error: false,
}
function dataReducer(state = initialState, action) {
  switch(action.type) {
    case FETCHING_DATA:
      return {
        ...state,
        isFetching: true,
      }
    case FETCHING_DATA_SUCCESS:
      return {
        ...state,
        isFetching: false,
        data: action.data,
      }
    case FETCHING_DATA_FAILURE:
      return {
        ...state,
        isFetching: false,
        error: true,
      }
  }
}react-native init reduxAll
cd reduxAll
yarn add redux react-redux redux-thunk redux-observable redux-saga rxjs
import React from 'react'
import {
  AppRegistry
} from 'react-native'
import { Provider } from 'react-redux'
import configureStore from './configureStore'
import App from './app'
const store = configureStore()
const ReduxApp = () => (
  <Provider store={store}>
    <App />
  </Provider>
)
AppRegistry.registerComponent('reduxAll', () => ReduxApp)
index.js
create redux files
Reducers folder
configureStore.js
constants.js
actions.js
Reducers - index.js
import { combineReducers } from 'redux'
import appData from './dataReducer'
const rootReducer = combineReducers({
    appData
})
export default rootReducerReducers - dataReducer.js
import { FETCHING_DATA, FETCHING_DATA_SUCCESS, FETCHING_DATA_FAILURE } from '../constants'
const initialState = {
  data: [],
  dataFetched: false,
  isFetching: false,
  error: false
}
export default function dataReducer (state = initialState, action) {
  switch (action.type) {
    case FETCHING_DATA:
      return {
        ...state,
        data: [],
        isFetching: true
      }
    case FETCHING_DATA_SUCCESS:
      return {
        ...state,
        isFetching: false,
        data: action.data
      }
    case FETCHING_DATA_FAILURE:
      return {
        ...state,
        isFetching: false,
        error: true
      }
    default:
      return state
  }
}
actions.js
import { FETCHING_DATA, FETCHING_DATA_SUCCESS, FETCHING_DATA_FAILURE } from './constants'
export function getData() {
  return {
    type: FETCHING_DATA
  }
}
export function getDataSuccess(data) {
  return {
    type: FETCHING_DATA_SUCCESS,
    data,
  }
}
export function getDataFailure() {
  return {
    type: FETCHING_DATA_FAILURE
  }
}
export function fetchData() {}configureStore.js
import { createStore } from 'redux'
import app from './reducers'
export default function configureStore() {
  let store = createStore(app)
  return store
}constants.js
export const FETCHING_DATA = 'FETCHING_DATA'
export const FETCHING_DATA_SUCCESS = 'FETCHING_DATA_SUCCESS'
export const FETCHING_DATA_FAILURE = 'FETCHING_DATA_FAILURE'app.js
import React from 'react'
import { View, Text, StyleSheet } from 'react-native'
let styles
const App = (props) => {
  const {
    container
  } = styles
  return (
    <View style={container}>
      <Text>Redux Examples</Text>
    </View>
  )
}
styles = StyleSheet.create({
  container: {
    marginTop: 100,
    alignItems: 'center'
  }
})
export default App
app.js
import { connect } from 'react-redux'
import { fetchData } from './actions'import connect from redux + reducer
Text
function mapStateToProps (state) {
  return {
    appData: state.appData
  }
}
function mapDispatchToProps (dispatch) {
  return {
    fetchData: () => dispatch(fetchData())
  }
}
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App)
attach actions and props to the component
app.js
console.log('props:', props);create fake api (api.js)
Text
const people = [
  { name: 'Nader', age: 36 },
  { name: 'Amanda', age: 24 },
  { name: 'Jason', age: 44 }
]
export default () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      return resolve(people)
    }, 2000)
  })
}
update configureStore.js
import { createStore, applyMiddleware } from 'redux'
import app from './reducers'
import thunk from 'redux-thunk'
export default function configureStore() {
  let store = createStore(app, applyMiddleware(thunk))
  return store
}update actions.js
import getPeople from './api'
export function fetchData() {
  return (dispatch) => {
    dispatch(getData())
    getPeople()
      .then((data) => {
        dispatch(getDataSuccess(data))
      })
      .catch((err) => console.log('err:', err))
  }
}update app.js
{
  props.appData.isFetching ? <Text>Loading</Text> :
    <Text onPress={() => props.fetchData()}>Fetch Data</Text>
}
{
  props.appData.data.length ? (
    props.appData.data.map((person, i) => {
      return <View key={i}>
        <Text>Name: {person.name}</Text>
        <Text>Age: {person.age}</Text>
      </View>
    })
  ) : null
}import { FETCHING_DATA, FETCHING_DATA_SUCCESS, FETCHING_DATA_FAILURE } from './constants'
import { put, takeEvery } from 'redux-saga/effects'
import getPeople from './api'
function* fetchData (action) {
  try {
    const data = yield getPeople()
    yield put({ type: FETCHING_DATA_SUCCESS, data })
  } catch (e) {
    yield put({ type: FETCHING_DATA_FAILURE })
  }
}
function* dataSaga () {
  yield takeEvery(FETCHING_DATA, fetchData)
}
export default dataSaga
saga.js
import { createStore, applyMiddleware } from 'redux'
import app from './reducers'
import createSagaMiddleware from 'redux-saga'
import dataSaga from './saga'
const sagaMiddleware = createSagaMiddleware()
export default function configureStore() {
  const store = createStore(app, applyMiddleware(sagaMiddleware))
  sagaMiddleware.run(dataSaga)
  return store
}configureStore.js
import { FETCHING_DATA } from './constants'
export function fetchData() {
  return {
    type: FETCHING_DATA
  }
}actions.js
import { FETCHING_DATA, FETCHING_DATA_SUCCESS, FETCHING_DATA_FAILURE } from './constants'
export function getData () {
  return {
    type: FETCHING_DATA
  }
}
export function getDataSuccess (data) {
  return {
    type: FETCHING_DATA_SUCCESS,
    data
  }
}
export function getDataFailure (error) {
  return {
    type: FETCHING_DATA_FAILURE,
    errorMessage: error
  }
}
actions.js
import { FETCHING_DATA } from './constants'
import { getDataSuccess, getDataFailure } from './actions'
import getPeople from './api'
import 'rxjs'
import { Observable } from 'rxjs/Observable'
const fetchUserEpic = action$ =>
  action$.ofType(FETCHING_DATA)
    .mergeMap(action =>
      Observable.fromPromise(getPeople())
        .map(response => getDataSuccess(response))
        .catch(error => Observable.of(getDataFailure(error)))
      )
export default fetchUserEpic
epic.js
import { createStore, applyMiddleware } from 'redux'
import app from './reducers'
import { createEpicMiddleware } from 'redux-observable'
import fetchUserEpic from './epic'
const epicMiddleware = createEpicMiddleware(fetchUserEpic)
export default function configureStore () {
  const store = createStore(app, applyMiddleware(epicMiddleware))
  return store
}
configureStore.js
import { getData } from './actions'
/* ... */
function mapDispatchToProps(dispatch) {
  return {
    fetchData: () => dispatch(getData())
  }
}app.js