Skip to main content

React Re-rendering Fixes

Causes of Re-rendering

Changes in Props

import React from 'react';

const MyComponent = props => {
return <div>{props.text}</div>;
};

Changes in State

import React, { useState } from 'react';

const MyComponent = props => {
const [count, setCount] = useState(0);

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

Changes in Context

import React, { useContext } from 'react';
import MyContext from './MyContext';

const MyComponent = props => {
const value = useContext(MyContext);

return <div>{value}</div>;
};

Changes in a Parent Component:

import React, { useState } from 'react';
import MyComponent from './MyComponent';

const ParentComponent = props => {
const [count, setCount] = useState(0);

return (
<div>
<div>Count: {count}</div>
<button onClick={() => setCount(count + 1)}>Increment</button>
<MyComponent text="Hello World" />
</div>
);
};

Changes in a Redux Store

import React from 'react';
import { useSelector } from 'react-redux';

const MyComponent = props => {
const value = useSelector(state => state.value);

return <div>{value}</div>;
};

Changes in a Hook Dependency

import React, { useState, useEffect } from 'react';

const MyComponent = props => {
const [count, setCount] = useState(0);

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

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

Re-rendering on Initial Mount

Sometimes a functional component may re-render during the initial mount. This can happen if the component uses a hook like useEffect() or useLayoutEffect() and doesn't specify the dependency array. Here is an example:

import React, { useState, useEffect } from 'react';

const MyComponent = props => {
const [count, setCount] = useState(0);

useEffect(() => {
console.log('Component rendered');
});

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

Changes in Objects or Arrays

If a functional component receives an object or array as a prop or state, and the object or array changes, it will re-render by default. This is because objects and arrays are reference types, and changes to their contents are not shallowly compared. Here is an example:

import React, { useState } from 'react';

const MyComponent = props => {
const [items, setItems] = useState([{ id: 1, text: 'Item 1' }, { id: 2, text: 'Item 2' }]);

const handleAddItem = () => {
setItems([...items, { id: 3, text: 'Item 3' }]);
};

return (
<div>
{items.map(item => (
<div key={item.id}>{item.text}</div>
))}
<button onClick={handleAddItem}>Add Item</button>
</div>
);
};

Inline Function props

If a functional component defines a new function inline, and the function is passed as a prop to a child component, it will cause the child component to re-render.

import React, { useState } from 'react';
import ChildComponent from './ChildComponent';

const MyComponent = props => {
const [count, setCount] = useState(0);

return (
<div>
<div>Count: {count}</div>
<button onClick={() => setCount(count + 1)}>Increment</button>
<ChildComponent onClick={() => console.log('Button clicked')} />
</div>
);
};

Changes in Local Variables

import React, { useState } from 'react';

const MyComponent = props => {
const [count, setCount] = useState(0);

let message = `Count: ${count}`;

if (count > 5) {
message = 'Count is greater than 5';
}

return (
<div>
<div>{message}</div>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};

Misusing Hooks, such as conditionally using a hook

import React, { useState } from 'react';

const MyComponent = props => {
let count;
if (props.showCount) {
[count, setCount] = useState(0);
}

return (
<div>
{props.showCount && <div>Count: {count}</div>}
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};