Joe Wayne

I talk about technology, programming and development.

Learn how to use React Hooks with these 3 tips

Introduction

React Hooks are a great tool for all React developers, but especially for beginners and intermediate developers. They are one of the main tools for improving the readability, reusability and maintainability of your code.

Think about it: it’s like replacing conventional building blocks with custom-made ones that make your application more stable and organized. And that’s what React Hooks can do for you!

What are React Hooks and why are they useful?

React Hooks were created to make life easier when it comes to managing state and side effects in React’s functional components. The idea was to simplify and make our code cleaner, easier to read, reuse and maintain.

Before Hooks, the thing was using class components, which were kind of like a puzzle – you could solve it, but it was sometimes a bit of a pain, especially when you had a lot of pieces. It was like looking for a needle in a haystack of code.

For example, do you want a counter that increments when you click a button? Super easy with useState. And when you want something to happen whenever that counter changes, just use useEffect. Take a look at the difference between doing this with React Hooks and class components.

// No reaction hooks
class Contador extends React.Component {
    state = {
        count: 0,
    }

    componentDidMount() {
        document.title = `Count: ${this.state.count}`
    }

    componentDidUpdate(prevProps, prevState) {
        if (prevState.count !== this.state.count) {
            document.title = `Count: ${this.state.count}`
        }
    }

    render() {
        return (
            <div>
                <p>Count: {this.state.count}</p>
                <button onClick={() => this.setState({ count: this.state.count + 1 })}>Increment</button>
            </div>
        )
    }
}

// Com React Hooks
function Counter() {
    const [count, setCount] = useState(0)

    useEffect(() => {
        document.title = `Count: ${count}`
    }, [count])

    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={() => setCount(count + 1)}>Increment</button>
        </div>
    )
}

React Hooks, especially useStateand useEffect, are like a toolbox that makes your React development experience much more productive. They encourage you to write more organized and reusable code, resulting in cleaner and more maintainable applications.

Oh, and React Hooks also include useRefuseContextuseReducerand a few others. Check out the full list . These hooks can be used to manage state, do some tricks with side effects, and access context data in a variety of ways.

1. Use useStateonly to manage state that is essential to your component

is useStatea powerful React Hook that lets you control state in your functional components. You can use it to keep track of anything that changes over time, like the value of a form field, the score in a game, or the list of items in your shopping cart.

Every time you use useState, you are creating a new state variable. This can accumulate and make your components slow and difficult to understand, so know how to use it correctly, creating only essential states for your component.

Do:

import React, { useState } from 'react';

const Count = () => {
    const [counter, setCount] = useState(0); // State essential: contador

    const handleIncrement = () => {
        setCount(prevContador => prevContador + 1);
    };

    return (
        <div>
            <p>Count: {counter}</p>
            <button onClick={handleIncrement}>Increment</button>
        </div>
    );
};

export default Count;

Here we are using it useStateto manage the essential state (counter) that is needed by the component, which is the right way.

Keeping only essential state in your component helps keep your code organized and easy to maintain. It also makes it easier to understand how your component works and how it changes over time.

Don’t do:

import React, { useState } from 'react';

const PerfilUsuario = () => {
    const [loggedIn, setLoggedIn] = useState(false);  // State don't essential: logged in

    const handleLogin = () => {
        setLoggedIn(true);
    };

    const handleLogout = () => {
        setLoggedIn(false);
    };

    return (
        <div>
            <p>User is logged in: {logado ? 'Yes' : 'No'}</p>
            <button onClick={handleLogin}>To enter</button>
            <button onClick={handleLogout}>To go out</button>
        </div>
    );
};

In this component, the state logadousing React Hooks is considered non-essential because it is not directly related to the main functionality or purpose of the component UserProfile. The purpose of this component is to display the user profile information, the main focus is not to manage the user’s login status.

Be careful about using non-essential states in your React Hooks component, as this can make your code complicated and difficult to read. It can also cause performance issues, especially when you have a large number of states.

2. Use useStateto control an immutable state

    Think of a state as something that cannot be changed directly. This means that you should never directly change the state variable. Instead, whenever you want to make a change, you create a new copy of that variable. This helps maintain the reliability of your data and prevents unexpected changes, ensuring that your program works as expected.

    Do:

    import React, { useState } from 'react';
    
    const ContadorImmutable = () => {
        const [counter, setCounter] = useState(0);  // Immutable state: counter
        const handleIncrement = () => {
            // Update the counter immutably using the setCounter function
            setCounter(prevCounter => prevCounter + 1);
        };
    
        return (
            <div>
                <p>Count: {counter}</p>
                <button onClick={handleIncrement}>Increment</button>
            </div>
        );
    };
    
    export default ContadorImmutable;
    

    In this example, we are using the setContadorto update the counter that should not be changed directly. This follows React’s rules, making everything more organized and reliable. Keeping the states immutable also makes it easier to understand and find errors in your code.

    Don’t Do:

    const ContadorMutable = () => {
        const [counter, setCounter] = useState(0);
    
        useEffect(() => {
            setCounter(counter + 1);
        });
    
        return (
            <div>
                <p>Count: {counter}</p>
            </div>
        );
    };
    

    The reason it is not correct to update state variables directly in useEffect, for example, is because this can generate infinite loops.

    In this example, the useEffectwill be triggered after each render, and it will increment the state variable count (counter), this means that the state variable will be incremented continuously, creating an infinite loop.

    3. Use useState pra organizar teu estado de uma maneira normalizada

    This means that you should organize the state(s) in a standardized and organized way. Instead of piling all the data into one pile, divide it into smaller, well-organized pieces. Each piece of data has its own unique identifier, which makes it easier to find, update, or work with it.

    Do:

    import React, { useState } from 'react';
    
    const StandardizedProducts = () => {
      const [products, setProducts] = useState({
        1: { id: 1, name: 'Product A' },
        2: { id: 2, name: 'Product B' }
      });  // Estado normalizado: produtos
    
      return (
        <div>
          <ul>
            {Object.values(products).map(product => (
              <li key={product.id}>{product.name}</li>
            ))}
          </ul>
        </div>
      );
    };
    
    export default StandardizedProducts;

    An example of how to use useStateand keep our data organized. Each product has its own special ID, which makes it easy to find and edit them. This way, we can search for our products and make changes when necessary. It’s like having a well-organized toolbox where each tool has its place – you can quickly find the right tool.

    Don’t Do:

    import React, { useState } from 'react';
    
    const StandardizedProducts = () => {
      const [prodycts, setProduct] = useState([
        { id: 1, name: 'Produto A' },
        { id: 2, name: 'Produto B' }
      ]);  // Estado não normalizado: produtos
    
      return (
        <div>
          <ul>
            {products.map(product => (
              <li key={product.id}>{product.name}</li>
            ))}
          </ul>
        </div>
      );
    };
    
    export default StandardizedProducts;

    A “denormalized” state using React Hooks means that the data is not organized efficiently. In this example, we are using useState to manage a list of products as well, but here each product is represented as an object inside an array and there is no identifier for that product.

    If you have a lot of products in your list, using a disorganized state with React Hooks can make it difficult to find and update specific products. It can also cause performance issues, especially if you’re displaying a list of all your products.

    Conclusion

    React Hooks, like useStateand useEffect, are powerful tools that can make your code more modular, reusable, clean, and maintainable.

    Use useStateto manage the component’s essential state, ensuring immutability and normalization. Use useEffectto handle side effects such as data fetching and subscriptions.

    By following these principles, you can achieve a new level of efficiency and elegance in your React development journey.

    Good hooks! 🚀

    Deixe um comentário

    O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *