This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const reducer = (state, { type, payload }) => { | |
switch (type) { | |
case 'ADD_FOOD_ITEM': | |
return { | |
foodItems: [ | |
...state.foodItems, | |
payload | |
] | |
} | |
default: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const App = ({ foodItems, addFoodItem }) => ( | |
<div> | |
<ul> | |
{ | |
foodItems.map(({ name, quantity }) => ( | |
<li>{name}, quantity: {quantity}</li> | |
)) | |
} | |
</ul> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) => { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fetchFoodItems = createActionCreator( | |
{ | |
pending: FOOD_ITEMS_FETCH_PENDING, | |
complete: FOOD_ITEMS_FETCH_COMPLETE, | |
error: FOOD_ITEMS_FETCH_ERROR, | |
}, | |
() => () => foodService.fetchFoodItems() | |
) | |
const addFoodItem = createActionCreator( |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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', |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const getFoodItemListViewState = createAsyncSelector({ | |
foodItems: getAsyncFoodItems, | |
funFactsById: getAsyncFunFactsById | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const getAsyncFoodItemsWithFacts = createAsyncSelector( | |
{ | |
foodItems: getAsyncFoodItems, | |
funFactsById: getFunFactsById | |
}, | |
({ foodItems, funFactsById }) => ( | |
mergeFunFactsIntoFoodItems(foodItems, funFactsById) | |
)) | |
) |