React Hooks/ Redux Store
React.js is an open-source JavaScript-based user interface library. It is hugely popular for web 🖥 and mobile app📱 development.
React follows the principle of component-based
architecture. A component
in React is an isolated and reusable piece of code. The components can be of two types – class components and functional components.
Before React version 16.8, developers 🧑💻could handle state and other React features only using class components. But with version 16.8, React introduced a new pattern called Hooks
.
If you write 🖥 a function component, and then you want to add some state to it, previously you do this by converting it to a class. But, now you can do it by using a Hook inside the existing function component.
Hooks allow function components to have access to state and other React features. Because of this, class components are generally no longer needed.
Hooks are functions that let you “hook into” React state and lifecycle features from function components.
With React Hooks, we can use state, and other React features, in a functional component. It empowers devs 🧑💻🧑💻🧑💻 to do functional programming in React.
React provides a bunch of standard in-built hooks:
useState
: To manage states. Returns a stateful value and an updater function to update it.useEffect
: To manage side effects like API calls, subscriptions, timers, mutations, and more.useContext
: To return the current value for a context.useReducer
: AuseState
alternative to help with complex state management.useCallback
: It returns a memorized version of a callback to help a child component not re-render unnecessarily.useMemo
: It returns a memoized value that helps in performance optimizations.useRef
: It returns a ref object with a.current
property. The ref object is mutable. It is mainly used to access a child component imperatively.
State Hooks
State lets a component “remember” information like user input. For example, a form component can use state to store the input value.
To add state to a component, use one of these Hooks:
useState
declares a state variable that you can update directly.useReducer
declares a state variable with the update logic inside a reducer function.
1) useState
useState
is a React Hook that lets you add a state variable to your component.
Call useState
at the top level of your component to declare a state variable.
useState
returns an array with exactly two values:
- The current state. During the first render, it will match the
initialState
you have passed. - The
set
function that lets you update the state to a different value and trigger a re-render. Calling theset
function does not change the current state in the already executing code.It only affects whatuseState
will return starting from the next render.
Updating state based on the previous state — updater function
you may pass an updater function to resolve this. if you do multiple updates within the same event, updaters can be helpful.
In most cases, there is no difference between these two approaches. React always makes sure that for intentional user actions, like clicks, the age
state variable would be updated before the next click.
Updating objects and arrays in state
Storing information from previous renders — {prop}
You might want to change a state variable when a prop changes.
Add the prevCount
state variable to track it. Add another state variable called trend
to hold whether the count has increased or decreased. Compare prevCount
with count
, and if they’re not equal, update both prevCount
and trend
. Now you can show both the current count prop and how it has changed since the last render.
I’m getting an error: “Too many re-renders”
React limits the number of renders to prevent an infinite loop.
Typically, this means that you’re unconditionally setting state during render, so your component enters a loop: render, set state (which causes a render), render, set state (which causes a render), and so on. Very often, this is caused by a mistake in specifying an event handler:
2) useReducer
Parameters
reducer
: The reducer function that specifies how the state gets updated. It must be pure, should take the state and action as arguments, and should return the next state. State and action can be of any types.initialArg
: The value from which the initial state is calculated. It can be a value of any type. How the initial state is calculated from it depends on the nextinit
argument.
useReducer
returns an array with exactly two values:
- The current state. During the first render, it’s set to
init(initialArg)
orinitialArg
(if there’s noinit
). - The
dispatch
function that lets you update the state to a different value and trigger a re-render.
Comparing useState
and useReducer
Code size: Generally, with useState
you have to write less code upfront.
Readability: useState
is very easy to read when the state updates are simple.
Debugging: When you have a bug with useState
, it can be difficult to tell where the state was set incorrectly, and why. With useReducer
, you can add a console log into your reducer to see every state update.
3) useEffect
useEffect(setup, dependencies?)-
setup
: The function with your Effect’s logic.
dependencies
: The list of all reactive values referenced inside of the setup
code
Some components need to stay connected to the network, some browser API, or a third-party library, while they are displayed on the page. These systems aren’t controlled by React, so they are called external.
Don’t rush to add Effects to your components. Keep in mind that Effects are typically used to “step out” of your React code and synchronize with some external system.
An Effect lets you keep your component synchronized with some external system (like a chat service).
Connecting to a chat server
uses an Effect to stay connected to an external system
Fetching data with Effects
You can use an Effect to fetch data for your component.
map widget or a video player
When you change the zoomLevel
prop of the Map
component, the Effect calls the setZoom()
on the class instance to keep it synchronized:
Usage -Connecting to an external system
Some components need to stay connected to the network, some browser API, or a third-party library, while they are displayed on the page. These systems aren’t controlled by React, so they are called external.
To connect your component to some external system, call useEffect
at the top level of your component:
Avoid below scenarios
- Updating state based on props or state
2. Adjusting some state when a prop changes
Every time the items
change, the List
and its child components will render with a stale selection
value at first. Then React will update the DOM and run the Effects. Finally, the setSelection(null)
call will cause another re-render of the List
and its child components, restarting this whole process again.
Below code is the solution for this :
4) useRef
useRef
is a React Hook that lets you reference a value that’s not needed for rendering.
Parameters
initialValue
: The value you want the ref object’scurrent
property to be initially. It can be a value of any type. This argument is ignored after the initial render.
Do not write or read ref.current
during rendering.
Returns
useRef
returns an object with a single property:
current
: Initially, it’s set to theinitialValue
you have passed. You can later set it to something else. If you pass the ref object to React as aref
attribute to a JSX node, React will set itscurrent
property.
By using a ref, you ensure that:
- You can store information between re-renders (unlike regular variables, which reset on every render).
- Changing it does not trigger a re-render (unlike state variables, which trigger a re-render).so refs are not appropriate for storing information you want to display on the screen. Use state for that instead. If you show
{ref.current}
in the JSX, the number won’t update on click. This is because settingref.current
does not trigger a re-render. Information that’s used for rendering should be state instead. - The information is local to each copy of your component (unlike the variables outside, which are shared).
Manipulating the DOM with a ref
sometimes you might need access to the DOM elements managed by React — for example, to focus a node, scroll to it, or measure its size and position. There is no built-in way to do those things in React, so you will need a ref to the DOM node.
Example: Focusing a text input
Example: Scrolling to an element
Example: Play and pause the video
5) useContext
useContext
is a React Hook that lets you read and subscribe to context from your component.
React Context is a way to manage state globally.
const value = useContext(SomeContext)
Passing Data Deeply with Context
Usually, you will pass information from a parent component to a child component via props.
But passing props can become verbose and inconvenient if you have to pass them through many components in the middle, or if many components in your app need the same information.
Context
Context lets a parent component provide data to the entire tree below it.
Step 1: Create the context
Step 2: Use the context
Next we’ll use the Context Provider to wrap the tree of components that need the state Context.
Wrap child components in the Context Provider and supply the state value. Now, all components in this tree will have access to the user Context.
Step 3: Use the useContext
Hook
In order to use the Context in a child component, we need to access it using the useContext
Hook.
First, include the useContext
in the import statement:
6) useCallback
The React useCallback
Hook returns a memoized callback function.
useCallback
is a React Hook that lets you cache a function definition between re-renders.
Think of memoization as caching a value so that it does not need to be recalculated.
The useCallback
and useMemo
Hooks are similar. The main difference is that useMemo
returns a memoized value and useCallback
returns a memoized function.
Returns
On the initial render, useCallback
returns the fn
function you have passed.
During subsequent renders, it will either return an already stored fn
function from the last render (if the dependencies haven’t changed), or return the fn
function you have passed during this render.
Skipping re-rendering of components
In other words, useCallback
caches a function between re-renders until its dependencies change.
Without useCallback and with memo
In JavaScript, a
function () {}
or() => {}
always creates a different function, similar to how the{}
object literal always creates a new object. Normally, this wouldn’t be a problem, but it means thatShippingForm
props will never be the same, and yourmemo
optimization won’t work. This is whereuseCallback
comes in handy:
By wrapping handleSubmit
in useCallback
, you ensure that it’s the same function between the re-renders
You will often see
useMemo
alongsideuseCallback
. They are both useful when you’re trying to optimize a child component. They let you memoize (or, in other words, cache) something you’re passing down:
useMemo
caches the result of calling your function. In this example, it caches the result of calling computeRequirements(product)
so that it doesn’t change unless product
has changed.
useCallback
caches the function itself. Unlike useMemo
, it does not call the function you provide. Instead, it caches the function you provided so that handleSubmit
7) useMemo
useMemo
is a React Hook that lets you cache the result of a calculation between re-renders.
The React useMemo
Hook returns a memoized value.
Think of memoization as caching a value so that it does not need to be recalculated.
Parameters
You need to pass two things to useMemo
:
- A calculation function that takes no arguments, like
() =>
, and returns what you wanted to calculate. - A list of dependencies including every value within your component that’s used inside your calculation.
Returns
On the initial render, useMemo
returns the result of calling calculateValue
with no arguments.
During next renders, it will either return an already stored value from the last render (if the dependencies haven’t changed), or call calculateValue
again, and return the result that calculateValue
has returned.
Usage
Skipping expensive recalculations
Skipping re-rendering of components
In some cases, useMemo
can also help you optimize performance of re-rendering child components.
How to tell if a calculation is expensive?
8) Custom Hooks
A custom Hook is a JavaScript function. The name of the custom Hook starts with “use” which can call other Hooks. A custom Hook is just like a regular function, and the word “use” in the beginning tells that this function follows the rules of Hooks. Building custom Hooks allows you to extract component logic into reusable functions.
When you have component logic that needs to be used by multiple components, we can extract that logic to a custom Hook.
Keeping Components Pure
Pure functions only perform a calculation and nothing more.
By strictly only writing your components as pure functions, you can avoid an entire class of baffling bugs and unpredictable behavior as your codebase grows.
- It minds its own business. It does not change any objects or variables that existed before it was called.
- Same inputs, same output. Given the same inputs, a pure function should always return the same result.
You could think of your components as recipes: if you follow them and don’t introduce new ingredients during the cooking process, you will get the same dish every time.
Pure functions don’t mutate variables outside of the function’s scope or objects that were created before the call — that makes them impure!
However, it’s completely fine to change variables and objects that you’ve just created while rendering.
How does React keep track of your app’s component structure?
React, and many other UI libraries, model UI as a tree. Thinking of your app as a tree is useful for understanding the relationship between components.
React uses tree structures to manage and model the relationship between components in a React app.
What is the DOM?
The Document Object Model (DOM) is a programming interface for web documents.
The DOM is not a programming language, but without it, the JavaScript language wouldn’t have any model or notion of web pages, HTML documents, SVG documents, and their component parts.
What is a DOM tree?
A DOM tree is a tree structure whose nodes represent an HTML or XML document’s contents.
The Render Tree
we have the concept of parent and child components, where each parent component may itself be a child of another component.
When we render a React app, we can model component relationships in a tree, known as the render tree.
See you soon with my next article. Until then, please take care of yourself, and stay happy.
REDUX
Redux is really:
- A single store containing a “global” state
- Dispatching plain object actions to the store when something happens in the app
- Pure reducer functions look at those actions and return an immutably updated state.
1) Create a Redux Store
2) Provide the Redux Store to React
3) Create a Redux State Slice
Redux Toolkit’s createSlice
API was designed to eliminate all the "boilerplate" with writing reducers, actions, and immutable updates!
Redux Toolkit’s createSlice
and createReducer
APIs use Immer inside to allow us to write "mutating" update logic that becomes correct immutable updates.
Redux and Side Effects
By itself, a Redux store doesn’t know anything about async logic. It only knows how to synchronously dispatch actions, update the state by calling the root reducer function, and notify the UI that something has changed.
Redux middleware was designed to enable writing logic that has side effects.
In practice, the single most common use case for side effects in a typical Redux app is fetching and caching data from the server.
Data Fetching
- Use RTK Query as the default approach for data fetching and caching
- If RTKQ doesn’t fully fit for some reason, use
createAsyncThunk
What is a “thunk”?
The word “thunk” is a programming term that means “a piece of code that does some delayed work”.
Thunks are best used for complex sync logic that needs access to dispatch
and getState
, or moderate async logic such as one-shot "fetch some async data and dispatch an action with the result" requests.
The most common use cases are:
- Moving complex logic out of components
- Making async requests or other async logic
- Writing logic that needs to dispatch multiple actions in a row or over time
- Writing logic that needs access to
getState
to make decisions or include other state values in an action
Why RTK Query for Data Fetching
Rdux intentionally designed the RTK listener middleware to be straightforward to use. It uses standard async/await
syntax.
It manages all the fetching, caching, and loading status logic for you.
RTK Query replaces the need to write any actions, thunks, reducers, selectors, or effects to manage data fetching. (In fact, it actually uses all those same tools internally.)