DEV Community

Cover image for How to force an update to Components in React
Maheedhar A
Maheedhar A

Posted on

How to force an update to Components in React

Have you ever come across a situation in which you submit the changes to your backend and the change is not visible in your react application? If yes, then, like me, you are using the useEffect hook to retrieve the data either from the backend/localStorage.

For this exact situation, there is another hook available in react called useReducer(). If you go to the official documentation of React, the definition of the useReducer hook is given as follows:

" useReducer is a React Hook that lets you add a reducer to your component. "

With it's syntax as:

const [state, dispatch] = useReducer(reducer, initialArg, init?)

As this definition isn't very straightforward, it is not very helpful if you are a beginner. The purpose of this article is to deconstruct this definition into simpler terms.

As it is easier to understand with an example, here is a simple react code which adds some data into the localStorage everytime the button is clicked.

Code:

import { useState, useEffect } from 'react';
import './App.css';

function App() {
  const [count, setCount] = useState(0);
  const [dataValues, setdataValues] = useState('');
  const [Loaded, setLoaded] = useState(false);
  useEffect(() => {
    let val;
    val = JSON.parse(localStorage.getItem('DataValues') || '[]');
    setdataValues(val);
    setLoaded(true);
  }, []);
  const handleClick = () => {
    const data = { source: 'meteor' };
    dataValues.push(data);
    localStorage.setItem('DataValues', JSON.stringify(dataValues));
  };

  return (
    <>
      {Loaded ? (
          <h1>React</h1>
          <div className="card">
            <button onClick={() => handleClick()}>Click me</button>
          </div>
          {dataValues.map((data, index) => (
            <div>
              <span key={index} style={{ textAlign: 'center', color: '#fff' }}>
                {data.source}
              </span>
              <br />
            </div>
          ))}
        </div>
      ) : (
        ''
      )}
    </>
  );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

If we run the development build of this application, we can observe this:

From the above video, it can be clearly observed that the changes are made visible only when the website is reloaded. This is unacceptable for single page applications. Hence, we need to find a way to force an update to the react application once we made changes to the localStorage/backend.

For this exact purpose, we use the useReducer react hook. The syntax for the useReducer hook is given below:

const [state, dispatch] = useReducer(reducer, initialArg, init?)

reducer => a function that defines how the state is updated
initialArg => sets the initial value of the state
init? => optional argument that specifies the initializer function that should return the initial state

The useReducer hook once initialized sets the value of state to init(initialArg)(if init is specified) or initialArg.

The changes we should make to our code to force an update is given below:

  const [dataValues, setdataValues] = useState('');
  const [Loaded, setLoaded] = useState(false);

  const [ignore, forceUpdate] = useReducer((x) => x + 1, 0);
  useEffect(() => {
    let val;
    val = JSON.parse(localStorage.getItem('DataValues') || '[]');
    setdataValues(val);
    setLoaded(true);
  }, [ignore]);
  const handleClick = () => {
    const data = { source: 'meteor' };
    dataValues.push(data);
    localStorage.setItem('DataValues', JSON.stringify(dataValues));
    forceUpdate();
  };

Enter fullscreen mode Exit fullscreen mode

What this does is that, whenever we call handleClick, after performing necessary actions the handleClick calls the forceUpdate function. The forceUpdate updates the value of the state from its initial state. Then, we are setting dependency of the useEffect hook to the state(ignore). Hence, whenever we click the button, ignore gets updated and then due to that the component is refreshed and we can instantly see the changes in the react application.

The output now looks like:

Feel free to leave a like if this article was helpful to you.

Top comments (1)

Collapse
 
davboy profile image
Daithi O’Baoill

Thank you