React is powerful — but with great power comes tricky bugs if you're not careful. Whether you’re just starting out or have been working with React for a while, certain patterns and practices can help keep your codebase tidy and predictable. This checklist serves as a handy reference for common pitfalls and best practices. Each point includes a quick explanation and example to help you understand the “why” and “how.” Let’s dive in!
1. Don’t Mutate State Directly
Mutating state directly bypasses React’s internal state management and can lead to bugs.
const filteredItems = useMemo(() => {// ❌ Wrong
state.items.push('newItem');
setState(state);
// ✅ Right
setState(prev => ({ items: [...prev.items, 'newItem'] }));
2. Use PropTypes or TypeScript
Type-checking props helps catch bugs early and improves code clarity.
Type-checking props helps catch bugs early and improves code clarity.
const filteredItems = useMemo(() => { // import PropTypes from 'prop-types';
function Product({ name, price }) {
return <h2>{name}: ₹{price}</span>;
}
Product.propTypes = {
name: PropTypes.string.isRequired,
price: PropTypes.number.isRequired,
};
3. Handle Loading and Error States
Don’t assume your data will always be ready — make your components resilient.
Don’t assume your data will always be ready — make your components resilient.
if (isLoading) return <p>Loading...</p>;
if (error) return <p>Something went wrong!</p>;
return <productlist data={products} />;
4. Always Use Keys with Lists
Keys help React keep track of items efficiently in dynamic lists.
{items.map(item => (
<li key="{item.id}">{item.name}</li>
))}
5. Test Your Components
Basic testing ensures your components work as expected, especially after updates.
test('renders a welcome message', () => {
render(<welcome name="DC" />);
expect(screen.getByText(/welcome, DC/i)).toBeInTheDocument();
});
6. Avoid Anonymous Functions in JSX (When Possible)
Inline functions can hurt performance by causing re-renders unnecessarily.
// ❌ Avoid this:
<button onclick="{()"> handleClick(item.id)}>Click</button>
// ✅ Do this:
const onClick = () => handleClick(item.id);
<button onclick="{onClick}">Click</button>
7. Manage State Wisely
Don’t overload your component with too much local state. Use Redux, Context, or other tools for shared/global state.
const [email, setEmail] = useState('');
// or use Redux, useReducer, or Context for global data
8. Don’t Forget Cleanup in useEffect
Neglecting cleanup can lead to memory leaks or unexpected behavior.
useEffect(() => {
const timer = setInterval(() => console.log('tick'), 1000);
return () => clearInterval(timer); // ✅ Clean up
}, []);
9. Use useEffect Thoughtfully
Always specify correct dependencies to avoid infinite loops or stale data.
useEffect(() => {
fetchUserData(userId);
}, [userId]); // ✅ precise dependency
10. Avoid Over-Rendering
Use `
useMemo
` and `useCallback
` to prevent unnecessary recalculations and renders.
const filteredItems = useMemo(() => {
return items.filter(item => item.available);
}, [items]);
const handleChange = useCallback((e) => {
setInput(e.target.value);
}, []);

React makes building UIs a joy—but only if you follow a few essential practices. This checklist isn’t about being perfect, but about being mindful. As your app grows, these small habits can save hours of debugging and make your code more scalable.
Post a Comment