React Hooks: Exploring the Versatility
React Hooks were first introduced in version 16.8 as a way to simplify state management and reduce duplicated code within React apps. Since then, developers have been able to create functional components with access to stateful behavior without having to change them into class components.
In this blog, we will explore what are React Hooks, their types, and examples that demonstrate their usage along with some best practices for leveraging Hooks effectively.
What are Hooks in React.js?
React Hooks enable the functional components to leverage state and other React capabilities, such as lifecycle methods, without having to transform them into class components. We can easily separate the reusable section of a functional component using React Hooks, which are simple JavaScript functions. Moreover, stateful hooks can manage side effects.
Programmers can manage state, handle side effects, consume context, and access the DOM using React’s built-in hooks, which include useState, useEffect, useContext, and useRef. In addition to designing hooks, developers can encapsulate and communicate their own stateful logic across multiple components.
Developers can now build cleaner, more reusable code using hooks by dividing logic into smaller, more focused functions. Using multiple hooks within a single component simplifies reasoning about the component’s state and behavior.
Types of Hooks in React
Following is the most widely used React Hooks list. Let’s look into the types in detail:
useState
Functional components can now store and modify values over time by utilizing this hook.
useEffect
You can use this hook to perform side effects such as requesting data from a server or modifying the DOM after the component has been rendered.
useContext
Passing props down the component tree for data sharing across components can be replaced by using this hook as an alternative.
useCallback
By memorizing a function, this hook enables optimizing efficiency by avoiding unnecessary re-renders in dependent child components.
useMemo
By minimizing pointless re-computations of a value, this hook memorizes it, enabling you to improve efficiency.
useReducer
Functional components can handle complex states by using this hook to update a state based on past states and actions.
useRef
The useRef hook provides a way to create a mutable reference that persists across renders, allowing for the storage of references to DOM elements or other information that needs to be retrieved between renderings.
useLayoutEffect
For certain types of applications, this hook can be useful as it is executed synchronously after all DOM modifications, similar to useEffect.
To learn more about hooks in React.js and how they are implemented, you can pursue a React course.
React Hooks Example
Questions about best practices and resolving frequent problems will inevitably arise, despite React Hooks having a relatively straightforward API and a large user base with diverse applications.
Let’s look at a few examples:
Declare State Variable
Calling useState with an initial state value, such as initialStateValue, is all it takes to declare a state variable quickly and easily.
const DeclareStateVar = () => { const [count, setCount] = useState(100); return <div> State variable is {count}</div> } |
Create a State From a Function
A state can be initialized through a function by just being passed as an initial state value, as seen below:
const StateFromFn = () => { const [token, setToken] = useState( ( ) => { let token = window.localStorage.getItem(“my-token”); return token || “default#-token#” }) return <div>Token is {token}</div>} |
Update State Variable
Updating a state variable is very simple. You only need to make a single call to the updater function returned by the useState invocation, which takes the form const [stateValue, updaterFn] = useState(initialStateValue);
const UpdateStateVar = () => { const [age, setAge] = useState(19) const handleClick = () => setAge(age + 1) return ( <div> Today I am {age} Years of Age <div> <button onClick={handleClick}>Get older! </button> </div> </div> ) } |
UseReducer
It’s perfect for sophisticated state logic with a lot of state sub-values or dependence on prior state values. It is quite testable, depending on your use case. Below are the commands that need to be followed:
const initialState = { width: 15 }; const reducer = (state, action) => { switch (action) { case ‘plus’: return { width: state.width + 15 }; case ‘minus’: return { width: Math.max(state.width – 15, 2) }; default: throw new Error(“what’s going on?” ); } }; const Bar = () => { const [state, dispatch] = useReducer(reducer, initialState); return ( <> <div style={{ background: ‘teal’, height: ’30px’, width: state.width }}></div> <div style={{marginTop: ‘3rem’}}> <button onClick={() => dispatch(‘plus’)}>Increase bar size</button> <button onClick={() => dispatch(‘minus’)}>Decrease bar size</button> </div> </> ); }; } ReactDOM.render(<Bar />, document.getElementById(‘root’)); |
Fetching Data With Loading Indicator
The following are the commands you need to follow to fetch data with a loading indicator in React Hooks:
const fetchData = () => { const stringifyData = data => JSON.stringify(data, null, 2) const initialData = stringifyData({ data: null }) const loadingData = stringifyData({ data: ‘loading…’ }) const [data, setData] = useState(initialData) const [gender, setGender] = useState(‘female’) const [loading, setLoading] = useState(false) useEffect( () => { const fetchData = () => { setLoading(true) const uri = ‘https://randomuser.me/api/?gender=’ + gender fetch(uri) .then(res => res.json()) .then(({ results }) => { setLoading(false) const { name, gender, dob } = results[0] const dataVal = stringifyData({ …name, gender, age: dob.age }) setData(dataVal) }) } fetchData() }, [gender] ) return ( <> <button onClick={() => setGender(‘male’)} style={{ outline: gender === ‘male’ ? ‘1px solid’ : 0 }} > Fetch Male User </button> <button onClick={() => setGender(‘female’)} style={{ outline: gender === ‘female’ ? ‘1px solid’ : 0 }} > Fetch Female User </button> <section> {loading ? <pre>{loadingData}</pre> : <pre>{data}</pre>} </section> </> )} |
Best Practices for Using React Hooks
The following are some recommendations for using React Hooks:
- React Hooks should only be used in functional components since they are not designed for class components.
- You should only call hooks from within other hooks or at the top level of your component, as it is the most crucial rule. Nested functions, loops, or conditions should never use them.
- The most common hook used for maintaining state in React apps is useState. For basic state values such as booleans and strings, it performs exceptionally well.
- Manage side effects in your React components using useEffect. You can use it to modify the DOM, fetch data from APIs, or establish event listeners.
- To optimize performance, use useCallback and useMemo. These functions can save values and functions that do not require recalculation on every render, resulting in better performance for your React components.
- If you require transferring state between components that are not directly connected to each other in the component tree, you should consider using React Context. It provides a way to pass data down the component tree without the need to pass props at each level.
- To make your code more reusable and simpler, use hooks wisely and avoid overusing them, as it can make your code more complex and difficult to understand. Using hooks is appropriate only when they simplify and enhance the readability of your code.
React Hooks can help you write shorter, more readable, and easier-to-maintain React code. To make sure that your code is effective, free of bugs, and simple to understand, it’s crucial to adhere to these best practices.
Conclusion
Hooks in React.js are an efficient means of accelerating application development by relieving developers from the need to create class components to utilize state and other React features. More developers will probably use this fantastic addition to the React library in the future.