- useEffectReact Hooks — Part 2

📄 Table of Contents
- useRef
- useReducer
- useState
- useEffect
- useMemo vs useCallback
- useContext
- useQuery
- useLayoutEffect
▬▬▬▬▬▬▬▬▬▬▬▬▬ ✦ ✦ ✦ ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
A key difference between class and functional components is the fact that class components have a state (stateful) while functional components are stateless.
Stateless components do not use the “this” keyword.
Reminder: React first updates the DOM i.e., goes inside return
statement, and then it calls any function that is passed into useEffect().


➪ Using useRef As useState Replacement
You might know useRef
as a tool to reference native DOM elements in order to focus on an input or to perform other similar DOM interactions. — but that’s NOT the only thing you can do with it.
Snippet of example usage from React docs:
function TextInputWithFocusButton() { const inputEl = useRef(null); const onButtonClick = () => {
// `current` points to the mounted text input element
inputEl.current.focus();
}; return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
useRef
can be used as an alternative to useState or useReducer.
The difference: Whenever its value changes, it does NOT force a render cycle. Therefore, in many typical cases of React development, useState is already a good choice — yet, in some, for example, the above one, useRef is much better.
Here is how to use it.
Translating a useState example to useRef
After importing useRef similar to the other hooks:
import { useRef } from "react"
Instead of using the destructuring syntax and getting a function for changing the state out of it, we treat useRef like a normal object.
Compared to useState, the console.logs do no longer appear whenever we type something into the input. Nevertheless, the value is actually there — the React dev tools provide us with evidence:
Summing up
If you want to have state in your components, that triggers a rerender when changed, go with useState or useReducer. If you do not want to have state, triggering a rerender, go with useRef.
For more @ https://medium.com/codex/usestate-useref-react-9f2398606d51
➪ useMemo and useCallback
Both of these hooks are similar in that they are used to memoize
.
The main difference is that useMemo
can be used to memoize any value including functions, while useCallback
can only be used to memoize functions.
➪ useState()
The useState
hook is a special function that lets us add state to a function component. The useState
hook takes an initial value and returns a stateful value and a function to update it.
In classes, the state
is always an object, but with hooks, the state is not necessarily an object, it can be of any type.
Syntax:
With useState hook the initial value of the state, the method to update the state, and the current value of the state everything can be written in a single line of code.
This syntax is known as Array Destructuring which is one of the features of ES6.
useState with the previous value of state
Sometimes we need to access the previous value of the state to update the current state, this can be done by passing a function to useState in the previous example. This function will have access to the previous value, and return an updated value.
Here’s an example of a counter component that updates the state using useState hook with the previous value of the state
useState with Object
Now we’ll see another example that makes use of the useState Hook when our State is an Object. Let’s try to print the full name of a person, based on values entered in the firstName and LastName field.
We’ll take values from the state and update it onChange of input fields.
In the above example, the state object is holding firstName and lastName properties, and these values are updated as soon as the user enters something in the input field.
Now, you might have noticed that we are merging states inside the onChange function using the spread operator with fullName i.e. {…fullName}. It is because unlike setState() the useState hook doesn’t automatically merge state objects. Hence we have to do manual merge by using a Spread Operator as you can see in the above example.
When dealing with Objects or Arrays, always make sure to spread your state variable and then call the setter function
➪ useEffect

While viewing the page, let’s say you chose the button that says “RED.” componentDidUpdate is then invoked. The terminal will now print out “The component was updated!” followed by “RED.” If you decide to choose the blue button, componentDidUpdate will be invoked again, as it would be each time you chose a different button. componentDidUpdate is executed any time the component has re-rendered.
How can we do this in a functional component?

When we first used the useEffect hook to mimic componentDidMount, we passed an empty array as the second argument. Because there is an empty array in the second argument, this string will no longer be logged to the console during if the component is rendered again. To mimic componentDidUpdate, we will add the dependency in an array as the second argument.
For running useEffect conditionally we need to pass an additional parameter which is an array
. In this array
, we specify either prop
or state
which we need to watch for. Then this function will be executed only if those states or props are updated.
If you want to run useEffect only on the component mount, you can pass an empty array instead of passing any prop or state.
To perform any action on component unmount using useEffect hook, the function that is passed to useEffect can return another function that will be executed when the component will unmount. So, whatever we return is a cleanup function.
➪ useReducer
useReducer is more performant than useState in the example above since we’re replacing multiple useState calls (which can cause multiple re-renders) with one useReducer call.
The difference in performance is not significant enough for this to be a concern, but it is worth noting that there is a slight performance benefit to taking the useReducer approach in similar scenarios.
Check out the two different implementations below for the getUsers()
function and decide for yourself which is clearer.
useReducer implementation:
function usersReducer(state, action) {
switch (action.type) {
case "LOADING": {
return { loading: true, users: null, error: null };
}
case "LOADED": {
return { loading: false, users: action.users, error: null };
}
case "ERROR": {
return { loading: false, users: null, error: action.error };
}
default: {
throw new Error(`Unhandled action type: ${action.type}`);
}
}
}function UsersList() {
const [state, dispatch] = React.useReducer(usersReducer, {
users: null,
loading: false,
error: null
}); function getUsers() {
dispatch({ type: "LOADING" });
fetchUsers().then(
users => {
dispatch({ type: "LOADED", users });
},
error => {
dispatch({ type: "ERROR", error });
}
);
}
}
useState implementation:
function UsersList() {
const [users, setUsers] = React.useState(null);
const [loading, setLoading] = React.useState(false);
const [error, setError] = React.useState(null); function getUsers() {
setLoading(true);
setError(null);
setUsers(null); fetchUsers().then(
users => {
setLoading(false);
setError(null);
setUsers(users);
},
error => {
setLoading(false);
setError(error);
setUsers(null);
}
);
}
}➪ useContext
➪ useContext
useContext is helpful any time you need to pass a prop through many nested children (to solve the prop-drilling problem), or when you need global state.
In the example below, even though we didn’t pass any props to the RandomNumber
or NumberGenerator
components, they can still access the necessary props through RandomNumberContext
.
for more @ https://medium.com/in-the-weeds/an-intro-to-advanced-react-hooks-a8af6397fe28
➪ useLayoutEffect
A notable change from class components to hooks is that componentDidMount
and componenentDidUpdate
fires before the UI is painted while useEffect
fires after the UI is painted. Why is this the new default? You may have code in useEffect
that can take a while, like an expensive call to the server, or a call to a third party service that shouldn’t block the UI from displaying content to the user.
If you want the previous behavior (of firing
useEffect
before the UI is painted) that's whereuseLayoutEffect
comes in.
The only time you need this is when you have code within useEffect
that has an observable visual effect — for example, when you are scrolling to the bottom of a window or when you are resizing an element. If you find that the UI is jumping around based on code in useEffect
, try replacing useEffect
with useLayoutEffect
.
➪ useQuery
import { useQuery } from "react-query"
It is a React library that handles state management by providing some hooks for updating, fetching and caching asynchronous data in React. Making an API call using React-Query it will cache the data the first time and serve the cache
data
in a subsequence API call. It also handles automatic JSON data transformation decreasing the amount of code needed.
Doing so will give a better user experience as well as improved app performance!
Here we will be going over an example of how to implement the “useQuery” hook starting with installing this dependency “Axios”.

Now that we have Axios installed here is an example of a React.js file. It uses React-Query to import the “useQuery” hook, as well as Axios, so we can fetch the data that we need.

source: https://johnnie-agonz71.medium.com/using-reacts-usequery-hook-to-fetch-data-cf25ee334f25
reference: https://medium.com/@nitheeromeshi/getting-started-with-react-query-e6159bb8fa09
Conclusion
React Query has completely removed the need we are having remote data inside the global state. we only have to tell the library where we need to fetch the data, and it will handle caching background updates and stale data without any extra code or configuration.
It also removes the usage of useState and useEffect hooks and replaces them with a few lines of React Query. It will definitely help to keep our application maintainable, responsive, and fast.