Source of truth === what submitted values are
(assuming you have a Redux application setup)
npm install --save redux-form
import { createStore, combineReducers } from 'redux'
import { reducer as formReducer } from 'redux-form'
const rootReducer = combineReducers({
// ...your other reducers here
// you have to pass formReducer under 'form' key,
// for custom keys look up the docs for 'getFormState'
form: formReducer
})
const store = createStore(rootReducer)
const exampleAction = {
type: 'EXAMPLE',
payload: [1,2,3]
}
const createExampleAction = () => {
return exampleAction
}
// UI
const ExampleComponents = props => (
<div>
<h3> props.exampleActionPayload </h3>
<button onClick={props.createExampleAction()} />
</div>)
//Reducer
initalState = {
exampleActionPayload: []
};
export default (state = initalState, action) => {
switch (action.type) {
case 'EXAMPLE'
return {
...state,
exampleActionPayload: action.payload
};
}
};
const createAsyncAction = (arg) => {
return {
type: 'ASYNC_ACTION',
payload: new Promise((resolve) => {
setTimeout(() => resolve(), 1000)
})
}
}
const callAPI = (arg) => {
return {
type: 'API_CALL',
payload: fetch('http://kylepotts.com')
}
}
export default (state, action) => {
if (typeof action.payload === "Promise") {
action.payload
.then(result => {
dispatch(promiseFulfilled(action.type, result));
})
.catch(err => {
dispatch(promiseFailed(action.type, err));
});
}
};
const promiseFulfilled = (actionType, result) => {
return {
type: `${actionType}_COMPLETE`,
payload: result
};
};
const promiseFailed = (actionType, failure) => {
return {
type: `${actionType}_FAIL`,
payload: failure
};
};
Good news, Redux Promise middleware can do this!
npm i redux-promise-middleware -s
//store creation
import { createStore, applyMiddleware, compose } from 'redux';
import promiseMiddleware from 'redux-promise-middleware';
import createHistory from 'history/createBrowserHistory';
import rootReducer from './redux/reducers';
export const history = createHistory();
const initialState = {};
const enhancers = [];
const middleware = [promiseMiddleware()];
const composedEnhancers = compose(applyMiddleware(...middleware), ...enhancers);
export default createStore(rootReducer, initialState, composedEnhancers);
const initalState = {
fooResults: null,
fooErrors: null,
};
export default (state = initalState, action) => {
switch (action.type) {
case 'FOO_FULFILLED':
return {
...state,
fooResults: action.payload
}
case 'FOO_REJECTED':
return {
...state,
fooErrors: action.payload
}
default:
return state;
}
};
const foo = () => ({
type: 'FOO',
payload: new Promise(),
})
// dispatch(foo())
// Then these actions are eventually dispatched
{
type: 'FOO_PENDING'
}
---
{
type: 'FOO_REJECTED'
error: true,
payload: {
...
}
}
||
{
type: 'FOO_FULFILLED'
payload: {
...
}
}
A special kind of Action
const step2Action = (name) => {
return {
type: 'STEP_2',
payload: name
};
}
const step1Action = () => {
return {
type: 'STEP_1',
payload: []
};
// need to dispatch step2Actions
dispatch(step2Action('Kyle'))
// but we don't have access to the dispatch function to dispatch an action
}
const step2Action = name => {
return {
type: "STEP_2",
payload: name
};
};
const step1Actions = () => {
return (dispatch) => {
dispatch(step2Action("Kyle"));
};
};
import { createStore, applyMiddleware, compose } from 'redux';
import promiseMiddleware from 'redux-promise-middleware';
import thunk from 'redux-thunk';
import createHistory from 'history/createBrowserHistory';
import rootReducer from './redux/reducers';
export const history = createHistory();
const initialState = {};
const enhancers = [];
const middleware = [thunk, promiseMiddleware()];
const composedEnhancers = compose(applyMiddleware(...middleware), ...enhancers);
export default createStore(rootReducer, initialState, composedEnhancers);
const secondAction = (number) => ({
type: 'TWO',
payload: number + 1,
})
const first = () => {
return (dispatch) => {
const response = dispatch({
type: 'ONE',
payload: Promise.resolve(1),
})
response.then((number) => {
dispatch(secondAction(number))
})
}
We can now take the result of an async action and pass it into another action!
GET swapi.co/api/people
{
"results": [
{
"name": "Luke Skywalker",
"height": "172",
"mass": "77",
"hair_color": "blond",
"skin_color": "fair",
"eye_color": "blue",
"birth_year": "19BBY",
"gender": "male",
"homeworld": "https://swapi.co/api/planets/1/",
}
]
}