Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent image from rerendering at every state change - React

In my component I have used an image in the following manner:

<div className="margin-10 flex-row-center">
                    <span>
                        <img src={spinner} className="spinner" />
                    </span>
                    <span className="padding-10">
                        We are checking your details
                    </span>
</div>

This is a few lines from a big functional component that has many states in it. This component is also sometimes used as a child to other components.

Now, whenever a state gets updated, a re-render of the component happens. Natural.

However, a visual update on the image is visible, which is not a good UX.

Any help, on how to prevent such unnecessary re-rendering of images. Also, if there is any other way to use images in React, that could solve this problem, will be helpful.

like image 317
Rohan Agarwal Avatar asked Jun 30 '20 08:06

Rohan Agarwal


People also ask

How do you prevent re-renders React?

There is no way to prevent a component that uses a portion of Context value from re-rendering, even if the used piece of data hasn't changed, even with useMemo hook. Context selectors, however, could be faked with the use of higher-order components and React. memo .

How do I stop infinite re-rendering in React?

To get rid of your infinite loop, simply use an empty dependency array like so: const [count, setCount] = useState(0); //only update the value of 'count' when component is first mounted useEffect(() => { setCount((count) => count + 1); }, []); This will tell React to run useEffect on the first render.

Does React Rerender everything on state change?

React components automatically re-render whenever there is a change in their state or props. A simple update of the state, from anywhere in the code, causes all the User Interface (UI) elements to be re-rendered automatically.


1 Answers

You can try to make image it's own pure component:

const Image = React.memo(function Image({ src }) {
  return <img src={src} className="spinner" />;
});

And then use it:

<div className="margin-10 flex-row-center">
  <span>
    <Image src={spinner} />
  </span>
  <span className="padding-10">
    We are checking your details
  </span>
</div>

Here is a working snippet:

const Image = React.memo(function Image({ src }) {
  return <img src={src} className="spinner" />;
});

function App() {
  const [counter, setCounter] = React.useState(0);
  const src =
    'https://en.bcdn.biz/Images/2018/6/12/f0d2c2ca-dc61-4613-9685-6c98cbb8a990.jpg';
  React.useEffect(() => {
    const t = setInterval(() => {
      setCounter((c) => c + 1);
    }, 100);
  });
  return (
    <div>
      <div>{counter}</div>
      <div>
        <Image src={src} />
      </div>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>


<div id="root"></div>
like image 118
HMR Avatar answered Oct 07 '22 11:10

HMR