=======
80296ec9ef49410e2eb29b3531ceac094d5e03bd
Thunk middleware for Redux.
npminstall--saveredux-thunk-fsa- import ReduxThunk from `redux-thunk`;+ import ReduxThunk from `redux-thunk-fsa`;
=======
[](https://travis-ci.org/reduxjs/redux-thunk)
[](https://www.npmjs.com/package/redux-thunk)
[](https://www.npmjs.com/package/redux-thunk)
```js
npm install redux-thunkMost tutorials today assume that you're using Redux Thunk 1.x. You may run into
issues when you run their code with 2.x. If you use Redux Thunk 2.x in
CommonJS environment,
don’t forget to add .default to your import:
- const ReduxThunk = require('redux-thunk')+ const ReduxThunk = require('redux-thunk').default
>>>>>>> 80296ec9ef49410e2eb29b3531ceac094d5e03bdMost importantly it adds support to FSA compliant actions. Consider the following example:
<<<<<<<HEADconstLOADING='INCREMENT/LOADING';constINCREMENT='INCREMENT/+';functionincrement(){return{type: INCREMENT_COUNTER};}functionloading(){return{type: LOADING};}functionincrementAsync(){return{type: INCREMENT,payload: dispatch=>{// sync incrementdispatch(loading());// async incrementreturnPromise.resolve(10);}};}=======importReduxThunkfrom'redux-thunk';// no changes here 😀Additionally, since 2.x, we also support a UMD build:
constReduxThunk=window.ReduxThunk.default;>>>>>>>80296ec9ef49410e2eb29b3531ceac094d5e03bdNormally this wouldn't be handled, but in conjunction with https://github.com/acdlite/redux-promise it allows you to create useful side-effects without too much hassle. It will eventually call action increment with payload 10 - and at this point you can handle it.
With a plain basic Redux store, you can only do simple synchronous updates by dispatching an action. Middleware extends the store's abilities, and lets you write async logic that interacts with the store.
Thunks are the recommended middleware for basic Redux side effects logic, including complex synchronous logic that needs access to the store, and simple async logic like AJAX requests.
For more details on why thunks are useful, see:
Stack Overflow: Dispatching Redux Actions with a Timeout
http://stackoverflow.com/questions/35411423/how-to-dispatch-a-redux-action-with-a-timeout/35415559#35415559
Dan Abramov explains the basics of managing async behavior in Redux, walking through a progressive series of approaches (inline async calls, async action creators, thunk middleware).Stack Overflow: Why do we need middleware for async flow in Redux?
http://stackoverflow.com/questions/34570758/why-do-we-need-middleware-for-async-flow-in-redux/34599594#34599594
Dan Abramov gives reasons for using thunks and async middleware, and some useful patterns for using thunks.What the heck is a "thunk"?
https://daveceddia.com/what-is-a-thunk/
A quick explanation for what the word "thunk" means in general, and for Redux specifically.Thunks in Redux: The Basics
https://medium.com/fullstack-academy/thunks-in-redux-the-basics-85e538a3fe60
A detailed look at what thunks are, what they solve, and how to use them.
You may also want to read the Redux FAQ entry on choosing which async middleware to use.
While the thunk middleware is not directly included with the Redux core library,
it is used by default in our
@reduxjs/toolkit package.
Redux Thunk middleware
allows you to write action creators that return a function instead of an action.
The thunk can be used to delay the dispatch of an action, or to dispatch only if
a certain condition is met. The inner function receives the store methods
dispatch and getState as parameters.
An action creator that returns a function to perform asynchronous dispatch:
constINCREMENT_COUNTER='INCREMENT_COUNTER';functionincrement(){return{type: INCREMENT_COUNTER,};}functionincrementAsync(){return(dispatch)=>{setTimeout(()=>{// Yay! Can invoke sync or async actions with `dispatch`dispatch(increment());},1000);};}An action creator that returns a function to perform conditional dispatch:
functionincrementIfOdd(){return(dispatch,getState)=>{const{ counter }=getState();if(counter%2===0){return;}dispatch(increment());};}A thunk is a function that wraps an expression to delay its evaluation.
// calculation of 1 + 2 is immediate// x === 3letx=1+2;// calculation of 1 + 2 is delayed// foo can be called later to perform the calculation// foo is a thunk!letfoo=()=>1+2;The term originated as a humorous past-tense version of "think".
<<<<<<< HEAD
npm install --save redux-thunk-fsa
=======
```bash
npm install redux-thunk
>>>>>>> 80296ec9ef49410e2eb29b3531ceac094d5e03bd
Then, to enable Redux Thunk, use
applyMiddleware():
import{createStore,applyMiddleware}from'redux';importthunkfrom'redux-thunk';importrootReducerfrom'./reducers/index';// Note: this API requires redux@>=3.1.0conststore=createStore(rootReducer,applyMiddleware(thunk));Any return value from the inner function will be available as the return value
of dispatch itself. This is convenient for orchestrating an asynchronous
control flow with thunk action creators dispatching each other and returning
Promises to wait for each other’s completion:
import{createStore,applyMiddleware}from'redux';importthunkfrom'redux-thunk-fsa';importrootReducerfrom'./reducers';// Note: this API requires redux@>=3.1.0conststore=createStore(rootReducer,applyMiddleware(thunk));functionfetchSecretSauce(){returnfetch('https://www.google.com/search?q=secret+sauce');}// These are the normal action creators you have seen so far.// The actions they return can be dispatched without any middleware.// However, they only express “facts” and not the “async flow”.functionmakeASandwich(forPerson,secretSauce){return{type: 'MAKE_SANDWICH',
forPerson,
secretSauce,};}functionapologize(fromPerson,toPerson,error){return{type: 'APOLOGIZE',
fromPerson,
toPerson,
error,};}functionwithdrawMoney(amount){return{type: 'WITHDRAW',
amount,};}// Even without middleware, you can dispatch an action:store.dispatch(withdrawMoney(100));// But what do you do when you need to start an asynchronous action,// such as an API call, or a router transition?// Meet thunks.// A thunk in this context is a function that can be dispatched to perform async// activity and can dispatch actions and read state.// This is an action creator that returns a thunk:functionmakeASandwichWithSecretSauce(forPerson){// We can invert control here by returning a function - the "thunk".// When this function is passed to `dispatch`, the thunk middleware will intercept it,// and call it with `dispatch` and `getState` as arguments.// This gives the thunk function the ability to run some logic, and still interact with the store.returnfunction(dispatch){returnfetchSecretSauce().then((sauce)=>dispatch(makeASandwich(forPerson,sauce)),(error)=>dispatch(apologize('The Sandwich Shop',forPerson,error)),);};}// Thunk middleware lets me dispatch thunk async actions// as if they were actions!store.dispatch(makeASandwichWithSecretSauce('Me'));// It even takes care to return the thunk’s return value// from the dispatch, so I can chain Promises as long as I return them.store.dispatch(makeASandwichWithSecretSauce('My partner')).then(()=>{console.log('Done!');});// In fact I can write action creators that dispatch// actions and async actions from other action creators,// and I can build my control flow with Promises.functionmakeSandwichesForEverybody(){returnfunction(dispatch,getState){if(!getState().sandwiches.isShopOpen){// You don’t have to return Promises, but it’s a handy convention// so the caller can always call .then() on async dispatch result.returnPromise.resolve();}// We can dispatch both plain object actions and other thunks,// which lets us compose the asynchronous actions in a single flow.returndispatch(makeASandwichWithSecretSauce('My Grandma')).then(()=>Promise.all([dispatch(makeASandwichWithSecretSauce('Me')),dispatch(makeASandwichWithSecretSauce('My wife')),]),).then(()=>dispatch(makeASandwichWithSecretSauce('Our kids'))).then(()=>dispatch(getState().myMoney>42
? withdrawMoney(42)
: apologize('Me','The Sandwich Shop'),),);};}// This is very useful for server side rendering, because I can wait// until data is available, then synchronously render the app.store.dispatch(makeSandwichesForEverybody()).then(()=>response.send(ReactDOMServer.renderToString(<MyAppstore={store}/>)),);// I can also dispatch a thunk async action from a component// any time its props change to load the missing data.import{connect}from'react-redux';import{Component}from'react';classSandwichShopextendsComponent{componentDidMount(){this.props.dispatch(makeASandwichWithSecretSauce(this.props.forPerson));}componentDidUpdate(prevProps){if(prevProps.forPerson!==this.props.forPerson){this.props.dispatch(makeASandwichWithSecretSauce(this.props.forPerson));}}render(){return<p>{this.props.sandwiches.join('mustard')}</p>;}}exportdefaultconnect((state)=>({sandwiches: state.sandwiches,}))(SandwichShop);Since 2.1.0, Redux Thunk supports injecting a custom argument using the
withExtraArgument function:
conststore=createStore(reducer,applyMiddleware(thunk.withExtraArgument(api)),);// laterfunctionfetchUser(id){return(dispatch,getState,api)=>{// you can use api here};}To pass multiple things, just wrap them in a single object. Using ES2015 shorthand property names can make this more concise.
constapi="http://www.example.com/sandwiches/";constwhatever=42;conststore=createStore(reducer,applyMiddleware(thunk.withExtraArgument({ api, whatever })),);// laterfunctionfetchUser(id){return(dispatch,getState,{ api, whatever })=>{// you can use api and something else here};}MIT