git clone https://github.com/Lazytangent/thunks.git && cd thunks && npm install
-
What is a thunk?
-
Besides being a fun way to make your English teacher super mad, a thunk is..
A subroutine used to inject an additional calculation into another subroutine. Thunks are primarily used to delay a calculation until its result is needed, or to insert operations at the beginning or end of the other subroutine.
-
In non-brain-melting terms...
A subprocess that runs and either waits to give its result when it's good and ready, or a subprocess that inserts itself into an already established process.
-
In terms of Redux...
A way for us to inject an async process into the Redux flow so it can eventually update our Redux store.
-
An article recommended by the people who brought us the
redux-thunk
package: https://daveceddia.com/what-is-a-thunk/It's a special (and uncommon) name for a function that's returned by another.
-
Wikipedia thinks...
The term originated as a humorous, incorrect past participle of "think". That is, a "thunk value" becomes available after its calculation routine is thought through, or executed.
-
To read more on the
redux-thunk
middleware, see their repo: https://github.com/reduxjs/redux-thunk
-
-
When should I use a thunk?
- The usual case is going to be when you need to make a fetch to some API, be it your own backend, or some 3rd party. Remember Express?? We're about to add all that knowledge back in!
-
Where does a thunk occur in the Redux flow?
-
Great question! Let's take a look at the old flow.
- The user has an
interaction
with our Application - That
interaction
sends anaction
, which as atype
andpayload
, to theDispatcher
- The
Dispatcher
sends anaction
to theReducer
- The
Reducer
takes in the currentstate
andaction
. It looks at all of its switch cases to see if theaction
'stype
has a match.- If a match is found, the
Reducer
runs the case with theaction
'spayload
and/or currentstate
- If not, it's best practice to return the current
state
- If a match is found, the
-
-
The user has an
interaction
with our Application -
That
interaction
sends aThunk
, which is a function (more on this in a bit), to theDispatcher
. -
The
Thunk Middleware
realizes that this is a function and NOT an action. It will then run the function, and when it's good and ready, it will dispatch an actualaction.
(POJO) -
The
Dispatcher
sends anaction
to theReducer
-
The
Reducer
takes in the currentstate
andaction
. It looks at all of its switch cases to see if theaction
'stype
has a match.- If a match is found, the
Reducer
runs the case with theaction
'spayload
and/or currentstate
- If not, it's best practice to return the current
state
- If a match is found, the
-
- The user has an
-
-
WHY?????
-
It just seems like we're adding an extra step into something that's already complex. Can't I just make my fetch calls in my component and then when that call is done, update my Redux store?
While it's possible to make these API calls from your components and dispatch synchronously on success, for consistency and reusability it's preferable to have the source of every change to our application state be an action creator. Thunks are a new kind of action creator that will allow you to do that.
In React / Redux, thunks enable us to avoid directly causing side effects in our actions, action creators, or components. Instead, anything impure will be wrapped in a thunk. Later, that thunk will be invoked by middleware to actually cause the effect. By transferring our side effects to running at a single point of the Redux loop (at the middleware level), the rest of our app stays relatively pure. Pure functions and components are easier to reason about, test, maintain, extend, and reuse.
-
-
HOW? Let's DO THIS! Let's take a look at the App first, just to see what it does, and so on and so forth.
-
Let's install the
redux-thunk
middleware.-
It basically looks like this.
const thunk = ({ dispatch, getState }) => (next) => (action) => { if (typeof action === 'function') { return action(dispatch, getState); } return next(action); };
-
-
Let's import
redux-thunk
into our store -
Now we need to add this middleware to our
applyMiddleware()
-
Let's go to
store/card.js
and let's look at the structure of aThunkCreator
. -
Head on over to App.js and let's change the import from the
ActionCreator
to theThunkCreator
. -
This means that we'll have to remove it from our dispatch.
-
Let's move all update logic to the ThunkCreator
-
Let's test it. Did it break?
-
Let's write the
ThunkCreator
withfetch
.-
A
ThunkCreator
is a function that intakes the params used at invocation. It then returns another function that intakesdispatch
. It should eventually dispatch an action (POJO).const Thunk = (param1, param2) => async (dispatch) => { const res = await fetch('api/something'); const { thing } = await res.json(); dispatch(definedAction(thing)); };
-
-
API Fetch
https://deckofcardsapi.com/api/deck/new/draw/?count=1