Where were we?
In my last blog post I was trying to explain in my limited, beginner understanding how Redux works in React. I had gone over how Redux takes the store out of the components and centralizes it. This gives the ability to access the store from any component.
Now what?
Having access to the state from anywhere is great and all but what about making changes to the state. There needs to be ways to change the state based on user interactions. This is where actions and reducers come in.
One of the functions that comes with creating the store this way is dispatch(action)
. Dispatching an action is the only way to trigger a change in the state.
An action is simply just a JavaScript object with a property of type
. Here is a very basic example.
const increaseCount = { type: 'INCREASE_COUNT' }
This action could be called something like this.
this.props.dispatch(increaseCount)
Dispatch sends this action to the reducer to then alter the state. A reducer is a function that takes an action and returns the new state. The action describes what is happening and it is the reducer's job to return the new state based on the action.
For the above example, a simple reducer might look like this.
function reducer(state = {
count: 0,
}, action) {
switch (action.type) {
case 'INCREASE_COUNT':
return { count: state.count + 1 };
default:
return state;
}
}
Here the initial state is set as 0 and calling dispatch with increaseCount
as the argument tells the reducer to run the action type of 'INCREASE_COUNT'
. It then returns the new state which is the old state +1.
The switch case format is a standard one that allows you to have other ways to alter the state. The reducer knows which case to use by the action type given to it.
This is obviously a very simple example and things can get really complicated quickly. As a beginner though, I am trying to keep it simple to not confuse myself, much less others.
What about Thunk?
Thunk is a middleware that can be used with our Redux store. Thunk lets you call action creators that return a function instead of an action object. That function receives the store's dispatch method, which is then used to dispatch regular synchronous actions inside the function's body once the asynchronous operations have been completed (ref).
The reason this is needed is for apps that need to communicate with an API or perform side effects. In my project I have a an API to get movie data as a well as a Rails backend that saves information from my app. For both of those I am making fetch calls to get information. Fetch is an asynchronous function so when Redux is running things synchronously you can run into issues.
Thunk is a way to make sure that promise that fetch gives back gets resolved before continuing code execution. Here is an example from my movie project.
export function fetchMovie(movie) {
return (dispatch) => {
fetch(`${apiURL}${movie}?api_key=${MY_API_KEY}`)
.then((resp) => resp.json())
.then((movie) => dispatch({ type: 'SEARCH_MOVIES', payload: movie}));
};
}
Instead of my action passing an object, I am returning a function that dispatches my 'SEARCH_MOVIES'
action type with the payload of the movie information I got back from my fetch call. That tells the reducer I have set up how to alter the state. In this case I am making the movie in my store be the one that is was just searched.
With all that information, we can now see the flow of how actions interact with the centralized state as well as seeing the need of middleware like Thunk to help as we use APIs to add more functionality to our web apps.
I am not sure how helpful any of that is but I know I benefitted from getting the chance to spend more time going over the lessons I had about Redux as well as searching online for more information.
Top comments (0)