Control when Saga Generators are Called with TakeLatest

Tyler Clark
InstructorTyler Clark

Share this video with your friends

Send Tweet
Published 4 years ago
Updated 3 years ago

We’ll dive into takeLatest, a saga helper that gives us the ability to control when our saga generator functions are called. We’ll then wire up takeLatest with our saga middleware and add it to the store.

Instructor: [00:00] Now that we have our saga generator function ready, we need to connect this to the store so that it could be initiated when the fetch Star Wars request action is dispatched by the UI "Load more" button.

[00:11] To do that, we'll navigate to our sagas file. We'll import takeLatest from redux-saga/effects as well as the types we use in our action creators and fetchPerson, which we just created, from our actions file. We'll make a new generator function -- we'll call it mySaga -- and yield takeLatest that takes a type, and our fetchPerson function. We'll export this out. Perfect.

[00:37] Now, as I mentioned, we need some way to connect our fetchPerson generator function with the store. This is accomplished by passing it to takeLatest as the second parameter and giving takeLatest the action creator type that when dispatched calls fetchPerson.

[00:52] We'll finish up by passing mySaga to the store next, but let's first talk about takeLatest. TakeLatest is listening to the store for any dispatched action creator that is carrying the type it's been provided. When it sees this type, it will call the provided generator function.

[01:09] If there's already an instance of the generator function running when it sees this dispatched type, it will cancel it and start another one. This way, there's only one, the latest function, running at a time.

[01:21] Now we'll navigate to the store file and add mySaga to the redux-saga middleware which will connect with the store. We'll bring in an applyMiddleware from Redux as well as createSagaMiddleware from redux-saga.

[01:36] Here, we're bringing mySaga. We'll create a const, call it sagaMiddleware = createSagaMiddleware(), update our createStore. We'll add applyMiddleware. Last, we'll do sagaMiddleware.run(mySaga).

[01:43] This .run method is referred to as a task. This is the glue between the store and our generator function, mySaga. This is also how the takeLatest method inside of mySaga has access to the dispatched actions.

[02:08] Before we head over to the UI to see how we did, let's install redux-saga. Back inside of our UI, let's double-check and make sure that our props are still going through. It looks like we still have our fetch Star Wars request action creator as well as our Star Wars reducer. Right now it's empty.

[02:31] When we click on this "Load more" button, it's supposed to fire this action creator, which will be picked up by a saga, and go out and fetch the Star Wars API. Awesome. It looks like it did work. You can see that we did fill our Star Wars reducer. It did map over it, which is exactly what we needed it to do.

Chris Frewin
Chris Frewin
~ 3 years ago

Hi Tyler, I have a quick question - I think I've sufficiently confused myself - I see you call the event creator in App.js using props, but from what I understand it is also an OK pattern in redux to do a direct import of the event creator like:

import { fetchStarWarsRequest } from '../actions';

and then switching the onClick handler simply to:

<button onClick={fetchStarWarsRequest}>Load More</button>

However, modifying the code this way (I cloned this branch of the repo and modified it as a check), the sagas function will not fire! What additional code do I need to use action creators this way?

While this example passes props only one level down, I don't always want to go through props to fire action creators (I'm incorporating sagas into a bigger app and need event creators a many different child layers, so the import way is a bit easier for me - well, easier if I could figure out how to get it working!)

Any help, tips, or comments would be appreciated!