But React doesn't re-render components if the previous props and current props are the same even when the component is not wrapped by React.memo().
Sure it does, both in functional components:
const Child = () => {
console.log('child rendering');
return 'foo';
};
const App = () => {
const [parentState, setParentState] = React.useState(0);
React.useEffect(() => {
setParentState(1);
}, []);
return (
<div>
<div>{parentState}</div>
<Child />
</div>
);
};
ReactDOM.createRoot(document.querySelector('.react')).render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div class='react'></div>
and in class components:
class Child extends React.Component {
render() {
console.log('child rendering');
return 'foo';
}
}
class App extends React.Component {
parentState = 0;
componentDidMount() {
this.setState({ parentState: 1 });
}
render() {
return (
<div>
<div>{this.parentState}</div>
<Child />
</div>
);
}
};
ReactDOM.createRoot(document.querySelector('.react')).render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div class='react'></div>
Unless you've set things up to memoize the component in some way, the component will re-render even if neither props nor state has changed.
The comparison that React.memo does to determine whether a component should be re-rendered whenever the component is called. That is, if you have
const SomeComponent = React.memo(function MyComponent(props) {
// ...
Then React.memo will perform comparisons whenever the engine, while rendering, comes across a call to SomeComponent, eg:
const App = () => {
return (
<div>
<SomeComponent />
</div>
);
};
Above, whenever App re-renders, SomeComponent will be called again. React.memo then decides whether the underlying component needs to be re-run, or whether the values returned by the previous render can be re-used. If it does need to be re-run, then it'll run the original MyComponent.