javascriptreactjsreact-functional-component

React - How to (force to) re-render a functional component?


I have a function component, and I want to force it to re-render.

How can I do so?
Since there's no instance this, I cannot call this.forceUpdate().


Solution

  • 🎉 You can now, using React hooks

    👉🏻 using useReducer (short answer)

    const [, forceUpdate] = useReducer(x => x + 1, 0);
    

    From React FAQ

    How to use:

    function MyComponent(){
      const [, forceUpdate] = useReducer(x => x + 1, 0);
    
      return (
        <div onClick={forceUpdate}>
          Click me to refresh
        </div>
      );
    }
    

    👉🏻 Using useState (more explicit answer)

    Using react hooks, you can now call useState() in your function component.

    useState() will return an array of 2 things:

    1. A value, representing the current state.
    2. Its setter. Use it to update the value.

    Updating the value by its setter will force your function component to re-render,
    just like forceUpdate does:

    import React, { useState } from 'react';
    
    //create your forceUpdate hook
    function useForceUpdate(){
        const [value, setValue] = useState(0); // integer state
        return () => setValue(value => value + 1); // update state to force render
        // A function that increment 👆🏻 the previous state like here 
        // is better than directly setting `setValue(value + 1)`
    }
    
    function MyComponent() {
        // call your hook here
        const forceUpdate = useForceUpdate();
        
        return (
            <div>
                {/*Clicking on the button will force to re-render like force update does */}
                <button onClick={forceUpdate}>
                    Click to re-render
                </button>
            </div>
        );
    }
    

    You can find a demo here.

    The component above uses a custom hook function (useForceUpdate) which uses the react state hook useState. It increments the component's state's value and thus tells React to re-render the component.


    EDIT

    In an old version of this answer, the snippet used a boolean value, and toggled it in forceUpdate(). Now that I've edited my answer, the snippet use a number rather than a boolean.

    Why ? (you would ask me)

    Because once it happened to me that my forceUpdate() was called twice subsequently from 2 different events, and thus it was reseting the boolean value at its original state, and the component never rendered.

    This is because in the useState's setter (setValue here), React compare the previous state with the new one, and render only if the state is different.