Skip to content

Instantly share code, notes, and snippets.

@sfrdmn
sfrdmn / mcr_post_02.jsx
Last active December 1, 2017 15:55
mcr_post_02
const reducer = (state, { type, payload }) => {
switch (type) {
case 'ADD_FOOD_ITEM':
return {
foodItems: [
...state.foodItems,
payload
]
}
default:
@sfrdmn
sfrdmn / mcr_post_03.jsx
Created December 1, 2017 15:56
mcr_post_03
const App = ({ foodItems, addFoodItem }) => (
<div>
<ul>
{
foodItems.map(({ name, quantity }) => (
<li>{name}, quantity: {quantity}</li>
))
}
</ul>
@sfrdmn
sfrdmn / mcr_post_04.jsx
Created December 1, 2017 15:57
mcr_post_04
const FOOD_ITEMS_FETCH_PENDING = 'FOOD_ITEMS_FETCH_PENDING'
const FOOD_ITEMS_FETCH_COMPLETE = 'FOOD_ITEMS_FETCH_COMPLETE'
const FOOD_ITEMS_FETCH_ERROR = 'FOOD_ITEMS_FETCH_ERROR'
const FOOD_ITEMS_ADD_PENDING = 'FOOD_ITEMS_ADD_PENDING'
const FOOD_ITEMS_ADD_COMPLETE = 'FOOD_ITEMS_ADD_COMPLETE'
const FOOD_ITEMS_ADD_ERROR = 'FOOD_ITEMS_ADD_ERROR'
// …
const addFoodItem = item => (dispatch) => {
@sfrdmn
sfrdmn / mcr_post_05.jsx
Created December 1, 2017 15:57
mcr_post_05
// Here we have a function which accepts a map of async states to action types
// as well as a thunk creator. It will yield a new thunk creator which wraps
// the provided one with our async state logic
const asyncActionCreator = (asyncTypes, createThunk) => (...args) => {
const thunk = createThunk(...args);
return (dispatch) => {
dispatch({ type: asyncTypes.pending })
// We assume here that the wrapped thunk produces a Promise
@sfrdmn
sfrdmn / mcr_post_06.jsx
Created December 1, 2017 15:58
mcr_post_06
const fetchFoodItems = createActionCreator(
{
pending: FOOD_ITEMS_FETCH_PENDING,
complete: FOOD_ITEMS_FETCH_COMPLETE,
error: FOOD_ITEMS_FETCH_ERROR,
},
() => () => foodService.fetchFoodItems()
)
const addFoodItem = createActionCreator(
@sfrdmn
sfrdmn / mcr_post_07.jsx
Created December 1, 2017 15:59
mcr_post_07
// Similar to the higher-order action creator, we accept a mapping of async
// states and action types, except this time, for convenience, in reverse.
// We then yield a reducer
const loadStateReducer = (asyncStates) => {
return (state = { loading: false, loaded: false, data: null }, action) {
const asyncState = asyncStates[action.type]
switch (asyncState) {
case 'pending':
return {
@sfrdmn
sfrdmn / mcr_post_08.jsx
Created December 1, 2017 15:59
mcr_post_08
const { combineReducers } = require('redux')
const foodItemsLoadState = loadStateReducer({
FOOD_ITEMS_FETCH_PENDING: 'pending',
FOOD_ITEMS_FETCH_ERROR: 'error',
FOOD_ITEMS_FETCH_COMPLETE: 'complete'
})
const foodItemAddState = loadStateReducer({
FOOD_ITEMS_ADD_PENDING: 'pending',
@sfrdmn
sfrdmn / mcr_post_09.jsx
Created December 1, 2017 16:00
mcr_post_09
const getAsyncFoodItems = state => state.foodItems
const getAsyncCookware = state => state.cookware
// Let’s introduce a new async resource containing fun facts about food
const getAsyncFunFactsById = state => state.funFactsById
@sfrdmn
sfrdmn / mcr_post_10.jsx
Created December 1, 2017 16:00
mcr_post_10
const getFoodItemListViewState = createAsyncSelector({
foodItems: getAsyncFoodItems,
funFactsById: getAsyncFunFactsById
})
@sfrdmn
sfrdmn / mcr_post_11.jsx
Created December 1, 2017 16:01
mcr_post_11
const getAsyncFoodItemsWithFacts = createAsyncSelector(
{
foodItems: getAsyncFoodItems,
funFactsById: getFunFactsById
},
({ foodItems, funFactsById }) => (
mergeFunFactsIntoFoodItems(foodItems, funFactsById)
))
)