Search code examples
react-nativereactjs-flux

REDUX: understanding a bit the concept + react native


So, I am working on a pretty straight forward mobile app that has these scenes:

  • a list of people
  • person profile
  • add form

now, what I do, when I first load the LIST scene, I make an API call (I have a list component that I populate once I get results from the API... state.people).

All good here... when I tap on a person he's profile opens, no extra API calls, just passing the person object from state.people array.

All good here as well.

When I open ADD NEW person and send the form I make another API call (I post the information and get the new Object back)...

now the bit that is confusing to me.

What I would like is to update the LIST scene state.people by making another API call (get all again) after I get the OK confirmation from the POST.

and then navigate to Person's profile.

but, I am outside the scope of the LIST scene (I am in ADD NEW form). So, what would be the correct redux logic for this one?

The LIST component is already mounted... how do I communicate to LIST if I am on different scene

all these binding actions to components properties is confusing too... why can't redux act like a global hub that would always be accessible and would always retain it's state (at least on mobile app)

There is really a lack of real app examples... so far I see only very simplified examples that are not very useful on the grand scale to understand the whole flow

the store I have

/**
* STORE
*/
'use strict';

import { createStore, applyMiddleware } from 'redux';
import reducer from './_reducer';
import promiseMiddleware from 'redux-promise-middleware';
import thunkMiddleware from 'redux-thunk';

const store = createStore(reducer, {}, applyMiddleware(
  thunkMiddleware,
  promiseMiddleware()
));

export default store;

and the actions I have:

import * as constants from '../../constants/constants';
import request from '../../utils/request';


export const getAll = () => ({
    type: constants.PEOPLE_FETCH,
    payload: request(constants.API_PATH + 'person', {method: 'GET'})
});

export const search = (data, searchTerm) => ({
    type: constants.PEOPLE_SEARCH,
    payload: _filter(data, searchTerm)
});

export const save = (data) => ({
    type: constants.PERSON_SAVE,
    payload: request(constants.API_PATH + 'person', {method: 'POST', body: JSON.stringify(data)})
});

Solution

  • This can be an example architecture for your app:

    1. Make a Redux store with list of people.
    2. On initial API call, update the store to contain the list fetched by API call.
    3. Wrap your app inside Provider and pass the store to the Provider.
    4. Use connect and mapStateToProps and mapDispatchToProps to connect the Redux store to React state.
    5. Whenever you update or insert new person, and get the new object, you need to dispatch an action which then goes to the reducer function which finally returns the updated Redux store, and dont worry with the re-rendering as React does the re-rendering itself whenever there is a change in a state.

    I'll give a small example of store/actions/reducer, with a react + redux app.

    store.js

    import { applyMiddleware, compose, createStore } from 'redux'
    import reducer from './reducer'
    import logger from 'redux-logger'
    
    // TOOD: add middleware
    let finalCreateStore = compose(
      applyMiddleware(logger())
    )(createStore)
    
    export default function configureStore (initialState = { todos: [] }) {
      return finalCreateStore(reducer, initialState)
    }
    

    actions.js

    let actions = {
      helloWorld: function(data){
        return {
          type: 'HELLO_WORLD',
          data: data
        }
      }
    };
    
    export default actions
    

    reducer.js // Please read from Redux docs that reducers need to be pure functions

    export default function myReducer(state = [], action) {
      switch (action.type) {
        case 'HELLO_WORLD':
          return 'welcome' + data;
        default:
          return state;
      }
    }
    

    Component.js (the React App) //In component whenever you receive new object, dispatch an action which will modify the store.

    import React, { Component } from 'react'
    import { connect } from 'react-redux'
    import { bindActionCreators } from 'redux'
    import actions from '../redux/actions'
    
    class App extends Component {
    
      handleClick() {
        store.dispath(action.helloWorld("jimmy")); //this dispatches an action, which goes to the reducer to change the state and adds 'welcome' before 'jimmy'
      }
    
      render() {
        return (
          <div onClick={this.handleClick.bind(this)}>
            {store.getState()} //getState function to access store values
          </div>
        )
      }
    
      }
    
      function mapStateToProps(state) {
        return state
      }
    
      function mapDispatchToProps(dispatch) {
        return {
          actions: bindActionCreators(actions, dispatch) //binds all the actions with dispatcher and returns them
        }
      }
    
      export default connect(mapStateToProps, mapDispatchToProps)(App)
    

    This works like whenever you click the 'div' in the React Component, it calls the function, handleClick(), in which there is an action dispatch. This action then calls the reducer itself to update the store. I know you might get confused that how is store getting updated. Its a bit confusing but for that you need to follow a basic tutorial to explain React+Redux.

    Please note this is not a runnable example, just a pseudocode. I recommend you to watch this youtube series to completely understand the redux stores+ react+webpack