useFocusEffect

Without React.useCallback

When you go onto the page, it will focus, and thus run the effect, and run the subscribe.

When you leave the page, it will run cleanup and thus un-subscribe.

With React.useCallback

If we have a state that is in dependency array, and that state changes, then it will make the React.useCallback re-generate.

Dependency array value changes STILL NEEDS a setState to notice the diff

ref – https://stackoverflow.com/questions/72508690/what-is-the-effect-if-a-useeffect-listens-to-a-non-state-value-of-having-a-non

1) Your component will only re-render if a value of a state variable has changed (setState at or above)] or
2) props that is been passed to this is changed where the props passed have to be a state (else it won’t rerender)

Thus, only change in value of state or props in a component re-renders the component

Let’s take a look at an example for 1)

Any variable can go in the dependency array, state or not. And as long as it’s in the array and it changes, useEffect’s callback gets re-executed.

BUT!, how will useEffect notice that change?

It does a diff whenever the component re-renders. And only a state change with a setState can trigger a render/re-render

Say we have the below component. We should have Hello Word logged in the console when the component renders the first time, and every time rand changes.

Clicking on that button changes rand, but we won’t have a new log, because there isn’t any re-render as no state has changed, so useEffect didn’t do a diff, so it’s not aware of the change.

Let’s take this same component, and change it a little bit, as below. Now every time you click on the button the component re-renders, because we are setting a state with setState, and while re-rendering if the value of rand changes from the previous one, we will get a new log.

Let’s take a look at an example for 2)

quickTickets is state.
We pass it via props into a functional component useEffectPublisher.

When parent state quickTickets change, it will propogate it to its child useEffectPublisher, which uses it
in its dependency array. This causes useEffectPublisher to re-render which leads the dependency array to do a diff on quickTickets.

createAsyncThunk and extraReducers

ref –

  • https://blog.logrocket.com/using-redux-toolkits-createasyncthunk/
  • https://redux-toolkit.js.org/api/createAsyncThunk

Within createSlice, synchronous requests made to the store are handled in the reducers object while extraReducers handles asynchronous requests, which is our main focus.

For example…with reducers

They are functions that receive the current state, and an action object that was dispatched.

src/features/posts/postsSlice.js

We export our reducers from postsSlice.actions so others can use it to dispatch.

src/features/posts/postsSlice.js

In the UI layer, they are dispatched like so:

src/features/posts/ReactionButtons.js

On the other hand…what if we want the async version of it?

Asynchronous requests created with createAsyncThunk accept three parameters:

  • an action type string
  • a callback function (referred to as a payloadCreator)
  • options object

Taking the previous code block as a Redux store for a blog application, let’s examine getPosts:

We have our initial state.

posts/fetchPosts is the action type string in this case.

Whenever this function is dispatched from a component within our application, createAsyncThunk generates promise lifecycle action types using this string as a prefix:

  • pending: posts/fetchPosts/pending
  • fulfilled: posts/fetchPosts/fulfilled
  • rejected: posts/fetchPosts/rejected

On its initial call, createAsyncThunk dispatches the posts/getPosts/pending lifecycle action type. The payloadCreator then executes to return either a result or an error.

In the event of an error, posts/getPosts/rejected is dispatched and createAsyncThunk should either return a rejected promise containing an Error instance, a plain descriptive message, or a resolved promise with a RejectWithValue argument as returned by the thunkAPI.rejectWithValue function (more on thunkAPI and error handling momentarily).

If our data fetch is successful, the posts/getPosts/fulfilled action type gets dispatched.

src/features/posts/postsSlice.js

Notice that we change the status property of state. How and where is state used?
First, notice getPostsStatus. In PostsList, we call useSelector on getPostsStatus.

useSelector is simply a hook to access Redux store’s state. This hook takes a selector function (getPostsStatus) as an argument. The selector is called with the store state.
In our case, it is state.posts.

Furthermore since we want to look at status property, then we’re accessing state.posts.status.

In other words, if state.posts.status === ‘loading’…

src/features/posts/PostsList.js

react-redux-saga-example-blog

Get started

So we create a ‘store’ folder first.
We import createSagaMiddleware from library redux-saga.

First we create the saga middleware.

Then we create the store by putting in:
– root reducer
– saga middleware

Once the saga middleware is in, we run it.

src/store/index.js

We use this finished created store in our index.js.
We put it on a Provider context so that everything in the middle can see it.

src/index.js

We ran saga middleware with rootSaga, so let’s see what that is.
We import all and fork from redux saga.

all simply runs multiple effects in parallel.
fork creates an effect that instructs the middleware to perform a non-blocking call of PostSaga.

So what is PostSaga?

It is a function that yield takeLatest of a function whenever an action is triggered.

So let’s explain what it means.

take creates an Effect that instructs the middleware to wait for a specified action on the Store.
The Generator is suspended until an action that matches pattern is dispatched.

The result of yield take(pattern) is an action object being dispatched.

takeLatest Forks a saga on each action (i.e GET_POSTS) dispatched to the Store that matches.
And automatically cancels any previous saga task started previously if it’s still running.

takeLatest doesn’t allow multiple Saga tasks to be fired concurrently.
As soon as it gets a new dispatched action, it cancels any previously-forked task (if still running).

takeLatest can be useful to handle AJAX requests where we want to only have the response to the latest request.

src/store/posts/saga.js

So in other words, we fork CartSaga, which listens to GET_POSTS and GET_POST_DETAILS call their respective handlers in a takeLatest fashion.

Saga

ref –

  • https://blog.logrocket.com/understanding-redux-saga-action-creators-sagas/
  • https://blog.devgenius.io/reactjs-simple-understanding-redux-with-redux-saga-f635e273e24a
  • https://dog.ceo/dog-api/
  • https://redux-saga.js.org/

Bare Redux won’t give us much flexibility. At its core, Redux is only a state container that supports synchronous data flows: every time an action is sent to the store, a reducer is called and the state is updated immediately.

But in an asynchronous flow, you have to wait for the response first;
then, if there’s no error, you can update the state.

And what if your application has a complex logic/workflow?

Redux uses middleware to solve this problem

A middleware is a piece of code that is executed after an action is dispatched, but before it reaches the reducer.
Its core function is to:

1) intercept the action sent to the reducer,
2) perform any asynchronous operation that may be present in the action,
3) and present an object to the reducer.

Redux Saga does this with the help of ES2015 generators

What are generator functions

Generators are functions that can be paused during execution and resumed, instead of executing all of a function’s statements in one pass.

When you invoke a generator function, it will return an iterator object. With each call of the iterator’s next() method, the generator’s body will be executed until the next yield statement, where it will then pause:

This can make asynchronous code easy to write and understand. For example, instead of doing this:

With generators, we can do this:

And with Redux Saga, we generally have a saga whose job is to watch for dispatched actions:

To coordinate the logic we want to implement inside the saga, we can use a helper function like takeEvery to spawn a new saga to perform an operation:

Using Redux Saga to handle multiple async requests

If there are multiple requests, takeEvery will start multiple instances of the worker saga; in other words, it handles concurrency for you.

Recalling our example, we could implement the fetchDogAsync() function with something like this (assuming we had access to the dispatch method):

by using yield and dispatch, we can have saga dispatch actions to reducers and do async operations (such as fetches) all in the order we want.
1) dispatch action requestDog
2) fetch dog data
3) with the returned data, we dispatch it to the reducer to save

Call

Just as in Redux you use action creators to create a plain object describing the action that will get executed by the Store, call creates a plain object describing the function call. The redux-saga middleware takes care of executing the function call and resuming the generator with the resolved response.

Redux Saga allows us to yield an object that declares our intention to perform an operation,
rather than yielding the result of the executed operation itself.

In other words, the above example is implemented in Redux Saga in this way:

Instead of invoking the asynchronous request directly, the method call will return only a plain object describing the operation like so:

Redux Saga then takes care of the invocation and return the result to the generator.

Put

The same thing happens with the put method. Instead of dispatching an action inside the generator, put returns an object with instructions for the middleware to dispatch the action.
Those returned objects are called effects.

Here’s an example of the effect returned by the call method:

Call vs Put

call function accepts rest arguments, which will be passed to api.fetchUser function.
Instructing middleware to call promise, it resolved value will be assigned to userData variable

Instructing middleware to dispatch corresponding action.

Composing Effects

We can very easily compose many effects into a complex workflow.
In addition to takeEvery, call, and put, Redux Saga offers a lot of effect creators for:
– throttling
– getting the current state
– running tasks in parallel
– cancel tasks, etc

Running Tasks In Parallel

The yield statement is great for representing asynchronous control flow in a linear style, but we also need to do things in parallel. We can’t write:

Because the 2nd effect will not get executed until the first call resolves. Instead we have to write:

Improving Performance

ref – https://www.telerik.com/blogs/debouncing-and-throttling-in-javascript

Throttling

No matter what happens, we’ll let you execute only after a period of time. Yes, you may keep asking in that period of time but we’ll ignore you.

Imagine yourself as a 7-year-old toddler who loves to eat chocolate cake! Today your mom has made one, but it’s not for you, it’s for the guests! You, being spunky, keep on asking her for the cake. Finally, she gives you the cake. But, you keep on asking her for more. Annoyed, she agrees to give you more cake with a condition that you can have the cake only after an hour. Still, you keep on asking her for the cake, but now she ignores you. Finally, after an interval of one hour, you get more cake. If you ask for more, you will get it only after an hour, no matter how many times you ask her.

This is what throttling is!

Throttling is a technique in which, no matter how many times the user fires the event, the attached function will be executed only once in a given time interval.

For instance, when a user clicks on a button, a helloWorld function is executed which prints Hello, world on the console. Now, when throttling is applied with 1000 milliseconds to this helloWorld function, no matter how many times the user clicks on the button, Hello, world will be printed only once in 1000 milliseconds. Throttling ensures that the function executes at a regular interval.

Debouncing

After a certain Cooling Period, we let you execute. But only if you’re quiet during that Cooling Period.

Consider the same cake example. This time you kept on asking your mom for the cake so many times that she got annoyed and told you that she will give you the cake only if you remain silent for one hour. This means you won’t get the cake if you keep on asking her continuously – you will only get it one hour after last time you ask, once you stop asking for the cake. This is debouncing.

In the debouncing technique, no matter how many times the user fires the event, the attached function will be executed only after the specified time once the user stops firing the event.

For instance, suppose a user is clicking a button 5 times in 100 milliseconds. Debouncing will not let any of these clicks execute the attached function. Once the user has stopped clicking, if debouncing time is 100 milliseconds, the attached function will be executed after 100 milliseconds. Thus, to a naked eye, debouncing behaves like grouping multiple events into one single event.

Both throttling and debouncing can be implemented with the help of the setTimeout function. So, let’s try to understand the setTimeout function.

setTimeout

setTimeout is a scheduling function in JavaScript that can be used to schedule the execution of any function. It is a web API provided by the browsers and used to execute a function after a specified time. Here’s the basic syntax:

The setTimeout function takes input as a callbackFunction that is the function which will be executed after the timer expires, and timeToDelay is the time in milliseconds after which the callbackFunction will be executed.

The setTimeout function returns a timerId, which is a positive integer value to uniquely identify the timer created by the call to setTimeout; this value can be passed to clearTimeout to cancel the timeout.

Example

Here, delayFuncExec will be executed after 100 milliseconds. timerId will store the integer returned by the setTimeout function.

clearTimeout

clearTimeout function is used to cancel the timeout previously established by calling the setTimeout function. clearTimeout takes the timerId returned by the setTimeout function as input and cancels its execution. So, if you want to cancel the execution of any setTimeout function, you can use clearTimeout function to cancel it by passing its timerId.

Now, let try to implement throttling and debouncing using JavaScript.

Implementing Throttling in JavaScript
Throttling will change the function in such a way that it can be fired at most once in a time interval. For instance, throttling will execute the function only one time in 1000 milliseconds, no matter how many times the user clicks the button.

throttling

In the above image, we can see that when the user is scrolling, the number of scroll event is much larger than the number of times throttling executed the function. Also, throttling executed the function at regular intervals, irrespective of the number of time scroll event is fired. Let’s check the code for the throttling.

Here’s the HTML for throttling example:

throttling.html

And here’s the JavaScript code for throttling example:

throttling.js

The above code renders a div with a scrollbar. We have added an event listener on the scroll event. Each time the user scrolls, an anonymous function is called that prints the number of times the scroll event is fired. When the user scrolls, we want to execute the makeAPICall method. But, as this method is heavy, attaching it to a scroll event directly will cause it to fire frequently. This may cause unnecessary load on the server. To prevent this, we have used the technique of throttling.

Let’s examine the above code line by line:

When the first scroll event is fired, throttleFunction is called with the makeAPICall function and delay in milliseconds as parameters.
Inside throttleFunction, timerId is undefined, as it has not been initialized yet. So, we will go ahead and schedule the func that is themakeAPICall function using the setTimeout function. The setTimeout function will execute the func or the makeAPICall function after 200 milliseconds. Now, timerId will have the unique id of this setTimeout function.
When the second event for the scroll is fired, timerId is not undefined inside throttleFunction, so the function will return without scheduling the execution of makeAPICall. If timerId is not undefined it means that a setTimeout function has already been scheduled, hence we do not need to schedule another function.
Thus, unless and until setTimeout executes the makeAPICall function, we will not be able to schedule another makeAPICall function using setTimeout. This ensures that the makeAPICall function will be called only once in an interval.
The point to be noted is: inside the setTimeout function we have changed timerId to undefined, so once the scheduled makeAPICall function has been executed and the user again performs the scroll, throttleFunction will schedule the execution of the makeAPICall function with the help of the setTimeout function. Thus the makeAPICall function will be executed only once in a given interval.

Static usage

Given:

Static methods access Static properties

If you declare a function to be static, it cannot access non-static properties such as test.

you must access a property that ALSO is also declared static like so:

This makes it consistent.

Instance Methods access static properties through Class name

But say you are forced to declare the function as an instance method:

In that case, you must the access static properties through the className.

You can test to see if both are same: