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
deck
- 839