Implement Synchronous Side Effects with Blocking Saga Effects

When some side effects depend on the return of other side effects, we need to stop or block the iteration through our sagas until these resolve. We control this stop and go pattern with blocking effects, such as call and take.

Code

You must be a Member to view code

Transcript

Instructor: 00:00 Inside of our saga generator, we're using two object effects from redux-saga, call and put. It does us no good to dispatch or put this action creator if the promise from fetching the Star Wars API is not resolved yet. We need saga to stop or block the iteration through the generator until we received our results.

00:20 A blocking call means that the saga yielded an effect and will wait for the outcome of its execution before resuming to the next instruction inside the yielding generator. In other words, call is considered a blocking effect while put is non-blocking because we really don't care if we return value.

00:41 Let's import take, race, and all from redux-saga/effects. We'll do yield take and a type. Then we'll make another action creator called confirmFetchRequest. We'll give it the same type. Perfect.

00:55 Let's say that when someone clicks on the "Load more" button in our UI, we want to have a modal pop-up and ask for confirmation before fetching the data. We would want to wait to fetch the API until a button inside the modal was pressed.

01:08 Take as well as race and all are also blocking effects. We can use take here to block load generator until it sees an action dispatched with the matching type. I can also do const destructure normal and custom, yield race with normal and a call, as well as custom and a call but have a different URL.

01:33 Let's pretend that our Star Wars API allowed for custom URLs. Let's also pretend that these custom endpoints returned quicker results. We want our app to use whichever endpoint is quickest.

01:44 We can figure this out by using the race effect. As the name implies, race will invoke the provided effects and return whichever resolves first. Once one effect wins, it will go through and clean up any other effects that are still pending. If we ended up using race, the next step would be to use an if check to dispatch a success action with the correct data.

02:08 I can also use all here. If I did not care which effect returned first, and I wanted to run multiple effects at the same time, we can do this using all. This works somewhere to promise it all where it will run all effects provided. Also, all is a hybrid effect, meaning it could be blocking or non-blocking.

02:27 Because we're using call on both inner effects, all, in this case, is blocking. However, if we used two non-blocking effects, all would be non-blocking. We'll stick to using the one call effect. We could open up our UI again and remove race and all. If we click on our UI button, we can see that we're no longer fetching the Star Wars API. This is because we added a take effect.

02:52 Remember, take is a blocking effect. FetchPerson will not continue on through until the provided type is seen on a dispatched action. We can confirm this by adding in a console log before the take and after the take. If we click on the button again, we can see entered in the console.

03:10 Back in our app index and our app CSS, we're going to need the state objects, so we'll put that up here at the top of the class with an open property of false. We'll extract this onClick method to a handler called handleFetchClick. We need to do two things inside this handleFetchClick. We need to call the Star Wars request action creator and update the state to true.

03:35 Next, we'll add XML for our modal. We'll do a div with a style that's dependent on the state to whether it shows it or not. Then we'll do a classier modal and add a button inside of that that will call another handler. We'll call it handleConfirmClick.

03:51 We'll create handleConfirmClick up here at the top where it does two things as well, calls the action creator confirmFetchRequest and updates the state back to false. Let's save this and see if we have any errors. Perfect.

04:07 We added HTML for our model. It will appear on the screen when the "Load more" button is clicked on. Inside of handleFetchClick, we're dispatching fetchStarWars request which is being listened for by sagas to enter our fetchPerson generator.

04:21 Now that our modal up here is we can click on the "Confirm" button which would dispatch confirmFetchRequest, this resolves the saga take effect inside fetchPerson and continues our generator. Our generator is no longer blocked at this time.