Overmind

By Lusan Das

#zionrocks #desktopteam

Disclaimer

This disclaimer informs the audience that the views, thoughts, and opinions expressed in the text belong solely to the author, and any similarity with the opinions was purely coincidental.

The saga of state management

Why so complex?

Folder Structure

  • Global action and reducer file
  • Action and reducer in the components file

Where should data reside?

  • Store
  • Component
  • Complex state tree
  • Uncontrolled codebase

Let's discuss more complexity

  • Complex Actions
  • Abstracting the outside world

A Complex Action

export function getDeliveryAddress(some_state) {
  return function(dispatch) {
    axios(some_config_object)
    .then(function(response) {
      let deliveryDetailsState;

      const deliveryAddressList = response.data.payload;

      let updatedDeliveryAddressList = deliveryAddressList.map((item, index) => {
        if(index !== 0) {
          // This isn't the item we care about - keep it as-is
          return item;
        }

        return {
          ...item,
          listIndex: 0,
        }
      });

      dispatch({
        type: types.FETCH_DELIVERY_ADDRESS_LIST_SUCCESS,
        some_state: some_state,
        deliveryAddressList: updatedDeliveryAddressList,
      });
    })
    .catch(function (error) {
      logException(error);

      return dispatch({
        type: types.FETCH_DELIVERY_ADDRESS_LIST_FAILURE,
        some_state: some_state,
        error
      });
    });
  }
}

Observables - fight fire with fire

/*----Enter Redux Observable----*/
//To handle side effects we have epics using rxjs
export function getDeliveryAddressEpic(action$) {
  return 
    action$
      .ofType(FETCH_DELIVERY_ADDRESS_LIST_SUCCESS)
      .switchMap((data) => {
        return 
          Observable
            .ajax(request_config_body)
            .map((response) => {
              const deliveryAddressList = response.data.payload;

              let updatedDeliveryAddressList = deliveryAddressList.map(
                (item, index) => {
                  if(index !== 0) {
                    // This isn't the item we care about - keep it as-is
                    return item;
                  }

                  return {
                    ...item,
                    listIndex: 0,
                  }
                }
              )

              return getDeliveryAddress(
                data.someState,
                updatedDeliveryAddressList
              );
            })
            .catch((error) => {
              //Handle Error
            })
      })
}

Hurray! A simple action

 
// Actions tidy yay!!
export function getDeliveryAddress(someState, response) {
  return {
    type: types.FETCH_DELIVERY_ADDRESS_LIST_SUCCESS,
    someState: someState,
    deliveryAddressList: response,
  }
}

Immutable

  • You probably don't need it
  • Overhead 17.2KB
  • Power of Independence

Enough of problems, we need a solution!

Enter Overmind!

import { createOvermind } from "overmind";
import { createHook, Provider } from "overmind-react";

const app = createOvermind({
  state: {
    count: 0
  },
  actions: {
    increaseCount({ state }) {
      state.count++;
    },
    decreaseCount({ state }) {
      state.count--;
    }
  }
});

const useApp = createHook();

function App() {
  const { state, actions } = useApp();

  return (
    <div className="App">
      <h1>{state.count}</h1>
      <button onClick={() => actions.decreaseCount()}>decrease</button>
      <button onClick={() => actions.increaseCount()}>increase</button>
    </div>
  );
}


Effects

// overmind/effects.js
import axios from 'axios'

export const api = {
  getCurrentUser() {
    return axios.get('/user')
  }
}


// overmind/actions.js
export const loadApp = async ({ effects, state }) => {
  state.currentUser = await effects.api.getCurrentUser()
}

Demo

The imperative way

Go Functional

Operators

Congratulations! You can now contribute to Codesandbox!!!

Happiness!

Conclusion

  • Abstraction
  • Going functional
  • Handling effects
  • Less learning curve
  • High developer productivity
 

Thank you!

Follow me on Twitter, Instagram!

 

@daslusan

 

 

References

deck

By Lusan Das