1

I've implemented a window resize event on initial component load. The event detects the window inner width and saves the value in a hook. Based on the width hook there is a second useEffect function, triggered on width change:

export const AppRouter = (props) => {

    const [width, setWidth] = useState(window.innerWidth);

    useEffect(() => {
        const handleResize = () => setWidth(window.innerWidth);
        window.addEventListener('resize', handleResize);
        return () => {
            window.removeEventListener('resize', handleResize);
        };
    }, []);

    useEffect(() => {
        setAppLayoutForViewportWidth();
    }, [width]);
}

Now to the unexpected behavior: the entire component rerenders on width hook change and not only the useEffect based on the width hook.

Can someone name the reason, why the entire component rerenders? Can I only rerender the width-based useEffect?

iamrobin.
  • 1,554
  • 3
  • 19
  • 31

1 Answers1

3

Why?

setState({}) always forces to re-render. (unless you return false in: shouldComponentUpdate(nextProps, nextState)) You can check this by putting a console log in

componentDidUpdate(prevProps, prevState) {
    console.log("Component did update")
}

Your setWidth(window.innerWidth);will change state due to it being: useState(window.innerWidth); which will force a rerender.

How to prevent it:

If you want to control when it rerenders, create a logic in shouldComponentUpdate to return false when you want to prevent rerender.

If you are in a functional component have a look at React.Memo. More on that in this thread: How can I prevent my functional component from re-rendering with React memo or React hooks?

React.Memo functions similarly to pure component. However, you can also adjust its behavior by passing it a function which defines what counts as equal. Basically, this function is shouldComponentUpdate, except you return true if you want it to not render.

const areEqual = (prevProps, nextProps) => true;

const MyComponent = React.memo(props => {
  return /*whatever jsx you like */
}, areEqual);
lehm.ro
  • 750
  • 4
  • 16