React has evolved a lot over the years, and staying up-to-date with new features can give your projects a major performance boost. Here are 10+ advanced and lesser-known tricks for React developers in 2025! 🧑💻
1. Optimize Expensive Renders with useDeferredValue
⏳
React 18 introduced useDeferredValue
, which helps optimize UI responsiveness by deferring non-urgent updates.
import { useDeferredValue } from 'react';
function SearchResults({ query }) {
const deferredQuery = useDeferredValue(query);
const results = useMemo(() => expensiveSearch(deferredQuery), [deferredQuery]);
return <ul>{results.map(item => <li key={item.id}>{item.name}</li>)}</ul>;
}
2. Automatic Batching in Async Code ⚡
React now batches state updates even in promises, reducing unnecessary re-renders.
import { useState } from 'react';
function App() {
const [count1, setCount1] = useState(0);
const [count2, setCount2] = useState(0);
const handleClick = async () => {
setCount1(c => c + 1);
setCount2(c => c + 1);
};
return <button onClick={handleClick}>Click Me</button>;
}
Both setCount1
and setCount2
are batched into a single render. 🎉
3. Memoize Components with Dynamic Prop Comparisons 🧠
Prevent unnecessary re-renders with React.memo
and a custom comparison function.
const MyComponent = React.memo(
(props) => {
return <div>{props.name}</div>;
},
(prevProps, nextProps) => prevProps.name === nextProps.name
);
4. Generate Unique IDs with useId
🆔
React's useId
is great for accessibility and generating stable, unique IDs.
import { useId } from 'react';
function FormField() {
const id = useId();
return (
<div>
<label htmlFor={id}>Name</label>
<input id={id} type="text" />
</div>
);
}
5. Preload Components with React.lazy
🚀
Improve perceived performance by preloading lazily loaded components.
const LazyComponent = React.lazy(() => import('./MyComponent'));
useEffect(() => {
import('./MyComponent');
}, []);
6. Custom Hooks for Cleaner Code 🧼
Extract reusable logic with custom hooks.
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return width;
}
function App() {
const width = useWindowWidth();
return <p>Window width: {width}px</p>;
}
7. Forward Refs for Better Component Composition 🔗
Pass refs through higher-order components with React.forwardRef
.
const InputWithRef = React.forwardRef((props, ref) => {
return <input {...props} ref={ref} />;
});
function App() {
const inputRef = useRef();
return (
<div>
<InputWithRef ref={inputRef} />
<button onClick={() => inputRef.current.focus()}>Focus Input</button>
</div>
);
}
8. Avoid Prop Drilling with Context API 🌐
Share state across deeply nested components using context.
const ThemeContext = React.createContext();
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('dark');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}
function ThemedButton() {
const { theme } = useContext(ThemeContext);
return <button className={theme}>Click Me</button>;
}
function App() {
return (
<ThemeProvider>
<ThemedButton />
</ThemeProvider>
);
}
9. Catch Errors with Error Boundaries 🛡️
Prevent app crashes by catching errors in the component tree.
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.error('Error:', error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
function App() {
return (
<ErrorBoundary>
<MyComponent />
</ErrorBoundary>
);
}
10. Render Outside DOM Hierarchy with Portals 🪄
Use React Portals to render modals outside the main DOM tree.
import ReactDOM from 'react-dom';
function Modal({ isOpen, onClose }) {
if (!isOpen) return null;
return ReactDOM.createPortal(
<div className="modal">
<button onClick={onClose}>Close</button>
<p>This is a modal!</p>
</div>,
document.getElementById('modal-root')
);
}
function App() {
const [isModalOpen, setModalOpen] = useState(false);
return (
<div>
<button onClick={() => setModalOpen(true)}>Open Modal</button>
<Modal isOpen={isModalOpen} onClose={() => setModalOpen(false)} />
</div>
);
}
11. Optimize Lists with Stable Keys 🔑
Always provide unique, stable keys to improve list rendering performance.
const items = ['Apple', 'Banana', 'Cherry'];
function ItemList() {
return (
<ul>
{items.map(item => (
<li key={item}>{item}</li>
))}
</ul>
);
}
12. Use Compound Components for Flexibility 🛠️
Create composable, flexible components with the compound component pattern.
function Tabs({ children }) {
const [activeIndex, setActiveIndex] = useState(0);
return React.Children.map(children, (child, index) => {
if (child.type === Tab) {
return React.cloneElement(child, {
isActive: activeIndex === index,
onClick: () => setActiveIndex(index),
});
}
return child;
});
}
function Tab({ isActive, onClick, children }) {
return (
<button className={isActive ? 'active' : ''} onClick={onClick}>
{children}
</button>
);
}
function App() {
return (
<Tabs>
<Tab>Tab 1</Tab>
<Tab>Tab 2</Tab>
</Tabs>
);
}
These are just some of the React tricks to take your development to the next level. Start using these today to build faster, more maintainable apps! 💻✨
Did you find these tips helpful? Let me know in the comments! 😊
Top comments (0)