DEV Community

Cover image for 🚀 Cool and Pro Tricks in ReactJS
Anupam Kumar
Anupam Kumar

Posted on • Edited on

🚀 Cool and Pro Tricks in ReactJS

Hey Dev.io crew! React is hands-down one of the slickest libraries for crafting dynamic, jaw-dropping user interfaces. Whether you’re grinding on massive apps or just leveling up your skills, I’ve got some advanced React tricks that’ll make your code cleaner, faster, and ready to scale. Let’s dive into the good stuff—complete with code snippets, real-world vibes, and a sprinkle of flair. Ready? Let’s roll! 💻

1. Leveraging React.memo and useCallback for Performance Optimization 🛠️
Re-renders slowing you down? Let’s tame that beast with React.memo and useCallback—your secret weapons for a snappy UI.

React.memo
Think of React.memo as a bouncer for your components—it only lets them re-render if the props actually change. Perfect for those heavy-duty functional components that keep getting hit with the same data.

import React from 'react';

const ExpensiveComponent = React.memo(({ data }) => {
  // Imagine some intense number-crunching or DOM-heavy logic here
  return <div>{data}</div>;
});
Enter fullscreen mode Exit fullscreen mode

Why it’s dope: It skips pointless re-renders, keeping your app lean and mean.

useCallback
This hook is your callback’s BFF—it locks down a function so it doesn’t get recreated every render unless its dependencies shift. Crucial when you’re passing callbacks to memoized kiddos.

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

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

  const handleClick = useCallback(() => {
    console.log('Clicked like a champ!');
  }, []); // No deps = this baby’s locked in

  return (
    <div>
      <button onClick={() => setCount(c => c + 1)}>Count: {count}</button>
      <ExpensiveComponent onClick={handleClick} />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Real-world flex: Picture a todo list with 100 items, each with a delete button. Without useCallback, every parent render churns out new functions, triggering re-renders in your memoized items. With it? Smooth as butter.

2. Code Splitting with React.lazy and Suspense ✂️
Big app, big bundle? Code splitting chops your code into bite-sized chunks, loading only what’s needed when it’s needed. React’s got your back with React.lazy and Suspense.

React.lazy
Load components on the fly with React.lazy. It’s like Netflix buffering—only grab what you’re about to watch.

import React, { Suspense } from 'react';

const LazyComponent = React.lazy(() => import('./LazyComponent'));

function App() {
  return (
    <Suspense fallback={<div>Loading... ⏳</div>}>
      <LazyComponent />
    </Suspense>
  );
}
Enter fullscreen mode Exit fullscreen mode

Suspense
Wrap it in Suspense, toss in a slick fallback UI, and your users won’t even notice the wait.

Why it’s clutch: Smaller initial bundles mean faster load times. Think e-commerce dashboards—load the product grid now, the analytics later. Check out React’s docs for more.

3. Custom Hooks for Cleaner Abstraction 🪝
Want reusable magic? Custom hooks let you bundle logic into neat little packages, keeping your components clean and focused.

useFetch Hook Example
Here’s a hook that fetches data, handles loading, and catches errors—all in one tidy box.

import { useState, useEffect } from 'react';

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    let isMounted = true;
    fetch(url)
      .then(res => res.json())
      .then(data => {
        if (isMounted) {
          setData(data);
          setLoading(false);
        }
      })
      .catch(err => {
        if (isMounted) {
          setError(err);
          setLoading(false);
        }
      });
    return () => { isMounted = false; }; // Cleanup crew
  }, [url]);

  return { data, loading, error };
}

export default useFetch;
Enter fullscreen mode Exit fullscreen mode

Plug it in:

import React from 'react';
import useFetch from './useFetch';

function DataDisplay({ url }) {
  const { data, loading, error } = useFetch(url);

  if (loading) return <div>Loading... ⏳</div>;
  if (error) return <div>Oops! Something broke. 😬</div>;

  return <div>{JSON.stringify(data)}</div>;
}
Enter fullscreen mode Exit fullscreen mode

When to use it: Fetching user profiles, posts, or stats—anytime you’re reusing API logic across components. Keeps your code DRY and your sanity intact.

4. Context API and useReducer for Global State Management 🌐
Need to share state across your app without prop-drilling hell? The Context API teamed up with useReducer is your lightweight state management MVP.

Set It Up
Here’s a global counter to flex your state muscles:

import React, { createContext, useReducer, useContext } from 'react';

const initialState = { count: 0 };
const StateContext = createContext();

function reducer(state, action) {
  switch (action.type) {
    case 'increment': return { ...state, count: state.count + 1 };
    case 'decrement': return { ...state, count: state.count - 1 };
    default: return state;
  }
}

export function StateProvider({ children }) {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <StateContext.Provider value={{ state, dispatch }}>
      {children}
    </StateContext.Provider>
  );
}

export const useGlobalState = () => useContext(StateContext);
Enter fullscreen mode Exit fullscreen mode

Use It Anywhere:

import React from 'react';
import { useGlobalState } from './StateProvider';

function Counter() {
  const { state, dispatch } = useGlobalState();

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

When it shines: Perfect for medium-sized apps—think user settings or a shopping cart. For mega-complex stuff, you might still reach for Redux, but this keeps it simple and scalable.

5. Advanced Styling Techniques: CSS-in-JS 🎨
Ditch static CSS for dynamic vibes with CSS-in-JS (like styled-components). It’s styling that flexes with your components.

Styled-Components Example
Check this button that switches styles based on props:

import styled from 'styled-components';

const Button = styled.button`
  background: ${props => props.primary ? '#007bff' : '#6c757d'};
  color: white;
  padding: 0.5rem 1rem;
  border: none;
  border-radius: 4px;
  cursor: pointer;

  &:hover {
    opacity: 0.8;
  }
`;

function App() {
  return (
    <div>
      <Button primary>Primary Button</Button>
      <Button>Secondary Button</Button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Why it’s fire: Scoped styles, no class name clashes, and dynamic props-based styling. Compared to CSS modules, it’s more integrated and flexible—ideal for theming or responsive UIs.

Wrap-Up 🎉
These React tricks—React.memo and useCallback for speed, code splitting for lean loads, custom hooks for clean code, Context API with useReducer for state domination, and CSS-in-JS for style swagger—will level up your game.

Drop your own hacks or hot takes in the comments—I’d love to hear how you’re crushing it with React. Happy coding, Dev.io fam! 🚀

Top comments (0)