# Commonly Made Mistakes with React Hooks **Published by:** [Farhad](https://paragraph.com/@asgarovf/) **Published on:** 2023-12-17 **URL:** https://paragraph.com/@asgarovf/commonly-made-mistakes-with-react-hooks ## Content React plays a huge role in our software development lifecycle building front-end services. With the continuous enhancements in NextJS, power of React is combined with Server Side Rendering (SSR), becoming the lead in front-end industry. Although there are many other front-end libraries and frameworks came out in the latest years, such as Vue.js and Svelte, React is the most preferred, as can be seen from Figure 1.[Figure 1]: Source - State of JS 2022React is a Javascript library that passes the authority of the codebase to developers and allows many customizations. It means that you write the code based on your pattern and there are only a few rules that should be followed. Therefore, the strong sides of React is achieved when it’s various features are used correctly with a correct pattern. State management, code splitting, memoization, server side rendering and many other features should be carefully designed by developers. In this article, we will dive deep into built-in and custom hooks, taking a look at commonly made mistakes in real-world usage of them.What is hook?As it can be understood from the name, hook is kind of a connection between your application parts. It is used to connect various React features to your UI components.Built-in HooksReact offers many built-in hooks which are available for developer’s usage without any dependency. For example, the useState hook declares a state variable inside the component that can be updated directly. There are many other built-in hooks which can be found in React documentation for hooks: https://react.dev/reference/react/hooksCustom HooksCustom hooks are more advance features, allowing an extension to built-in hooks. You are able to do anything you want with a custom hook, using the built-in and other custom hooks. For example, let’s say you are keeping a counter state in your component, using the useState built-in hook, and use it in multiple places. With a custom hook you can keep this state separately in single place and call it multiple times at multiple places without repeating yourself. The definition looks really similar to functions in programming right? Yes, hooks are very similar to functions, but the only difference is they can make use of built-in React hooks to build reusable code partitions. The only thing you should do to inform the React about custom hook definition is starting the function name with use prefix. Let’s write a custom hook as stated in this paragraph to implement a counter state:/* useCounter.ts */ type ReturnType = { counter: number; increment: () => void; decrement: () => void; } export const useCounter = (): ReturnType => { // You are able to use built-in hook const [counter, setCounter] = useState(0); // Increments the counter state const increment = () => { setCounter((prevState) => prevState + 1) } // Decrements the counter state const decrement = () => { setCounter((prevState) => prevState - 1) } // Return anything useful for you return { counter, increment, decrement } } And let’s use the hook we built in our component:/* MyComponent.tsx */ // Import the custom hook (assuming useCounter.ts is in the same directory) import { useCounter } from "./useCounter"; export const MyComponent = () => { // Call the hook to achieve the returned values from useCounter hook const { counter, increment, decrement } = useCounter() return ( <div> <p>Counter: {counter}</p> <button onClick={increment}>Increment</button> <button onClick={decrement}>Increment</button> </div> ) } If you define another component and name it MyComponent2.tsx, you will be able to use exact the same useCounter hook in your code for various reasons. This is pretty much of it about custom hooks. You are probably already thinking of many other things that you can build with hooks to not repeat yourself and keep the core UI components clear. Let’s get into the commonly made mistakes by developers before you built your ideas to make sure that your code is fine.1 - Naming ConventionAs we mentioned above, the custom hooks should be named with the prefix of use keyword to help the React to understand what is going on. As far as you start your function name with use keyword, your definition is correct programmatically. However, you should try naming the hooks based on the feature it implements to help other developers understanding why the hook is defined. Assume that you are building a hook to keep whether the user has connected their crypto wallet to the website. You should probably choose a name like useIsWalletConnected to clearly describe the hook’s purpose. Additionally, it is kind of a convention to choose a name without a use keyword for assigned variable. For example, as you can see from the example below, the variable name of isWalletConnected is same the as useIsWalletConnected except the use keyword.const isWalletConnected = useIsWalletConnected() 2 - Incorrect hook callsThe hooks are only available inside other hooks and components. It is common mistake to call a hook inside a normal Javascript function. In some frameworks, especially in web, the linters and Typescript will warn you about this mistake:[Figure 2] Example error arises with an incorrect hook usageHowever, sometimes you are not warned about this mistake. For example, in React Native code, you are able to call the hook inside a non-hook function which is a very important point that you should avoid.3 - Dependency array of useEffectuseEffect is a built-in hook in React that plays a huge role in component lifecycle. It allows you handling effects in component to synchronize your application state with external systems. You can read more about it from the link below. https://react.dev/reference/react/useEffect In a more general definition, the useEffect hook accepts two arguments, a function to be executed (1st argument) when one of the variables inside the dependency array (2nd argument) changes. The commonly made mistake is not adding a variable that is used inside useEffect to the dependency array. This causes a huge problem for the application state, since you are not accessing the latest values in the state. It is expected from developers to add all the used dependencies to the second argument of the useEffect hook. There is a really helpful eslint rule, called react-hooks/exhaustive-deps, to avoid making this mistake, which is built by React developers. I highly recommend using this eslint rule without ignoring it. https://www.npmjs.com/package/eslint-plugin-react-hooks4 - Clearing effectsWe mentioned above about useEffect hook. Let’s also give another example to the common mistake while using the useEffect. This hook is sometimes used for event subscription in your component. Let’s say you want to register a listener to your smart contract and respond to the events that are emitted from it with Ethers.js. According to documentation, you should use contract.on method to listen to event. The correct place for this registration is useEffect for sure. Let’s implement it:/* MyComponent.tsx */ export const MyComponent = () => { useEffect(()=>{ // Create your callback function const listener = () => { console.log("Event Received") } // Create a new Ethers contract instance const contract = new Contract("0xADDRESS", ABI, provider); // Register event contract.on("SomeEvent", listener) }, []) return ... // Some UI } According to the code written above, your listener function will be executed when the contract emits an event called SomeEvent. However, there is a problem. Let’s say your component is called inside a page, and after some time, you will navigate to different page. After the navigation happens, the event registration will still be active and listener function will be executed even if the MyComponent is not actively mounted on the screen. Additionally, when you come back to the page which uses MyComponent, the event registration will happen again, causing multiple subscriptions. Therefore, you should unregister this event to avoid this mistake. You can do this in return block of the useEffect. It is also known as componentWillUnmount() lifecycle in class components. You should follow the pattern below to unregister the subscription:/* MyComponent.tsx */ export const MyComponent = () => { useEffect(()=>{ // Create your callback function const listener = () => { console.log("Event Received") } // Create a new Ethers contract instance const contract = new Contract("0xADDRESS", ABI, provider); // Register event contract.on("SomeEvent", listener) // Unregister event return () => { contract.off("SomeEvent", listener) } }, []) return ... // Some UI } 5 - Conditional renderingHooks are sometimes rendered conditionally inside the components. This is not a expected usage and should be avoided. What is a conditional rendering? Let’s see by giving the example of useCounter hook that we implemented above./* MyComponent.tsx */ // Import the custom hook (assuming useCounter.ts is in the same directory) import { useCounter } from "./useCounter"; export const MyComponent = () => { const [someState, setSomeState] = useState(true); // Let's say you return an empty component when someState is false if (!someState) { return null; } // ERROR! Hooks should not be called conditionally const { counter, increment, decrement } = useCounter() return ( <div> <p>Counter: {counter}</p> <button onClick={increment}>Increment</button> <button onClick={decrement}>Increment</button> </div> ) } Instead, there are some tricky ways to render hooks conditionally. To do this you should create a separate React component and call the hook inside your component. Then, you can conditionally render this React component to also render the hook conditionally. Let’s see example below:/* MyComponent.tsx */ // Import the custom hook (assuming useCounter.ts is in the same directory) import { useCounter } from "./useCounter"; // Create a separate React component that calls the useCounter hook const MyConditionalComponent = () => { const { counter, increment, decrement } = useCounter() return ( <div> <p>Counter: {counter}</p> <button onClick={increment}>Increment</button> <button onClick={decrement}>Increment</button> </div> ) } export const MyComponent = () => { const [someState, setSomeState] = useState(true); // Let's say you return an empty component when someState is false if (!someState) { return null; } /* You can safely use the conditionally rendered component. With this way, you are also rendering the useCounter hook in a conditional way. */ return <MyConditionalComponent /> } 6 - Misunderstanding with global stateLet’s say you are calling useCounter hook inside your component. It can sometimes be thought that, wherever you use the useCounter it will use the same state, just like a global variable. However, this is not correct. Every time you call a useCounter hook, it creates a new and separate counter state, as can be also seen from Figure 3, which is not connected with other counter states.[Figure 3] Multiple useCounter hook callIf you want to somehow achieve the global state structure to use the same values when calling custom hooks, you should either use React Context, which is built-in functionality of React, or third-party State Management Libraries. I highly recommend using Recoil, which is maintained by Meta team and has high performance. https://recoiljs.org/7 - Returning UI Components from HooksHooks can also be used to build various UI components. You can basically create a functional component inside a custom hook, return and use it. However, this is not an expected usage for custom hooks. Try keeping your components and hooks separately and do not use hooks to build UI components. You can build needed utilities with hooks and call them inside the UI component to keep them clear.ConclusionWe covered 7 commonly made mistakes for React hooks in this article. These examples are mostly taken from my own past experience. I highly recommend taking these examples into consideration while building your custom hooks. Also, do not forget to always check React documentation for the correct information. https://react.dev/ ## Publication Information - [Farhad](https://paragraph.com/@asgarovf/): Publication homepage - [All Posts](https://paragraph.com/@asgarovf/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@asgarovf): Subscribe to updates - [Twitter](https://twitter.com/asgarovf): Follow on Twitter