Pure components and React.memo are essential tools in React.js for optimizing performance by preventing unnecessary re-renders. This chapter will cover the concepts from basic to advanced, providing detailed explanations and examples to ensure a comprehensive understanding.
A Pure Component in React is a component that performs a shallow comparison of its props and state to determine whether the component should re-render. If the props and state have not changed, the component does not re-render, which can improve performance.
import React, { PureComponent } from 'react';
class MyComponent extends PureComponent {
render() {
console.log('MyComponent render');
return {this.props.value};
}
}
export default MyComponent;
In this example, MyComponent will only re-render if its props.value changes.
React.memo is a higher-order component that memoizes a functional component. It behaves similarly to PureComponent but is used with functional components.
import React from 'react';
const MyComponent = React.memo(({ value }) => {
console.log('MyComponent render');
return {value};
});
export default MyComponent;
In this example, MyComponent will only re-render if its props.value changes.
Using Pure Component and React.memo can significantly improve the performance of a React application by reducing unnecessary re-renders. This is particularly useful in large applications with complex component trees.
Pure Component performs a shallow comparison of the current and previous props and state. If all props and state are equal (shallow comparison), the component does not re-render.
import React, { PureComponent } from 'react';
class MyComponent extends PureComponent {
render() {
console.log('MyComponent render');
return {this.props.value};
}
}
class App extends React.Component {
state = {
value: 0
};
increment = () => {
this.setState({ value: this.state.value + 1 });
};
render() {
return (
);
}
}
export default App;
value in the state is incremented.MyComponent only re-renders if this.state.value changes, as it performs a shallow comparison of props.React.memo works by memoizing the functional component. It performs a shallow comparison of the current and previous props. If all props are equal (shallow comparison), the component does not re-render.
import React, { useState } from 'react';
const MyComponent = React.memo(({ value }) => {
console.log('MyComponent render');
return {value};
});
function App() {
const [value, setValue] = useState(0);
const increment = () => {
setValue(value + 1);
};
return (
);
}
export default App;
value in the state is incremented.MyComponent only re-renders if value changes, as it performs a shallow comparison of props.
React.memo is used with functional components.class MyComponent extends PureComponent { ... }React.memo: const MyComponent = React.memo(function MyComponent(props) { ... })
import React, { PureComponent } from 'react';
class PureChild extends PureComponent {
render() {
console.log('PureChild render');
return Pure Component: {this.props.value};
}
}
class App extends React.Component {
state = {
value: 0
};
increment = () => {
this.setState({ value: this.state.value + 1 });
};
render() {
return (
);
}
}
export default App;
PureChild render is logged only when the value prop changes.PureChild.
import React, { useState } from 'react';
const MemoChild = React.memo(({ value }) => {
console.log('MemoChild render');
return Memo Component: {value};
});
function App() {
const [value, setValue] = useState(0);
const increment = () => {
setValue(value + 1);
};
return (
);
}
export default App;
Output:
MemoChild render is logged only when the value prop changes.MemoChild.React.memoBy default, React.memo performs a shallow comparison of props. You can provide a custom comparison function to control the behavior.
import React, { useState } from 'react';
const MemoChild = React.memo(
({ value }) => {
console.log('MemoChild render');
return Memo Component: {value};
},
(prevProps, nextProps) => {
// Custom comparison: only re-render if value is an even number
return prevProps.value % 2 === nextProps.value % 2;
}
);
function App() {
const [value, setValue] = useState(0);
const increment = () => {
setValue(value + 1);
};
return (
);
}
export default App;
MemoChild re-renders only if value changes from even to odd or vice versa.While Pure Component and React.memo can improve performance, they can also introduce overhead due to shallow comparisons. Use them judiciously, especially in large component trees or when dealing with deeply nested objects.
React.memo for complex comparison logic, but be cautious of the performance implications.React.memo for functional components.React.memo provide fine-grained control over re-renders.In this example, we’ll create a simple app that displays a list of users and a counter. The user list component will be a Pure Component to prevent unnecessary re-renders when the counter updates.
import React, { PureComponent, Component } from 'react';
// PureComponent to display a list of users
class UserList extends PureComponent {
render() {
console.log('UserList render');
const { users } = this.props;
return (
User List
{users.map(user => (
- {user.name}
))}
);
}
}
class App extends Component {
state = {
users: [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Smith' },
{ id: 3, name: 'Jack Johnson' }
],
counter: 0
};
incrementCounter = () => {
this.setState({ counter: this.state.counter + 1 });
};
render() {
return (
Counter: {this.state.counter}
);
}
}
export default App;
users prop changes.UserList component does not re-render because the users prop has not changed.In this example, we’ll create a simple app that displays a list of products and a search bar. The product list component will use React.memo to prevent unnecessary re-renders when the search query updates.
import React, { useState, memo } from 'react';
// Memoized functional component to display a list of products
const ProductList = memo(({ products }) => {
console.log('ProductList render');
return (
Product List
{products.map(product => (
- {product.name}
))}
);
});
function App() {
const [products] = useState([
{ id: 1, name: 'Laptop' },
{ id: 2, name: 'Smartphone' },
{ id: 3, name: 'Tablet' }
]);
const [search, setSearch] = useState('');
const handleSearchChange = (e) => {
setSearch(e.target.value);
};
return (
);
}
export default App;
products prop changes.ProductList component does not re-render because the products prop has not changed.Pure Component and React.memo are powerful tools in React.js that help optimize performance by preventing unnecessary re-renders. By understanding how they work and applying best practices, you can build more efficient and responsive React applications.Happy coding !❤️
