Fixing Unwanted Re-renders in a Nested Component Tree Using React Context

Published: (December 13, 2025 at 06:44 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

Cover image for Fixing Unwanted Re-renders in a Nested Component Tree Using React Context

Not all React performance issues show up as errors.
Some appear quietly during development, when a simple UI interaction feels heavier than it should.

This article walks through a real dev‑time issue caused by prop drilling and poor state placement — and how restructuring state fixed unnecessary re‑renders, API calls, and heavy UI updates.

The application used React and rendered a Highcharts‑based visualization (expensive to re‑render). Deep in the component tree (2–3 levels down) there was a child component with a button.

Requirement

When the button is clicked, show a modal. Simple on paper.

The Initial Implementation

The modal state was defined in the parent component.

const Parent = () => {
  const [isModalOpen, setIsModalOpen] = useState(false);

  useEffect(() => {
    fetchData();
  }, []);

  return ;
};

setIsModalOpen was passed down multiple levels via props until it reached the button.

 setIsModalOpen(true)}>
  Open modal

Functionally, this worked, but architecturally it was problematic.

What I Observed During Testing

While casually testing the feature in development, I noticed:

  • A visible UI pause on button click
  • Highcharts re‑rendering
  • API calls being triggered again

Every click caused a parent state update, which meant:

  • Parent component re‑rendered
  • Side effects tied to the parent executed again
  • Expensive UI re‑initialized unnecessarily

Nothing was broken — but the cost was real.

The Root Cause

The issue was state placement.

  • The modal state was UI‑only.
  • It lived in a parent component responsible for data fetching and heavy rendering.
  • Prop drilling tightly coupled a local interaction to global side effects.

This is a common architectural leak in React applications as they grow.

The Fix: Isolate UI State with Context

Remove modal state from the parent entirely and introduce a dedicated Context for modal visibility.

import { createContext, useState } from "react";

const ModalContext = createContext(null);

export const ModalProvider = ({ children }) => {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <ModalContext.Provider value={{ isOpen, setIsOpen }}>
      {children}
    </ModalContext.Provider>
  );
};

Place the provider at the top‑most boundary where modal state makes sense. Components that need to open or close the modal consume the context directly:

import { useContext } from "react";

const { setIsOpen } = useContext(ModalContext);

No prop drilling. No parent involvement.

The Result

After this change:

  • Parent components no longer re‑rendered on modal open.
  • API calls executed only when explicitly intended.
  • Highcharts remained stable.
  • UI interactions felt immediate and predictable.

The behavior was the same for users, but the architecture was cleaner and more performant.

Key Takeaways

  • Prop drilling can hide performance issues, even when code is correct.
  • UI‑only state should not live alongside data‑fetching logic.
  • If a button click triggers unrelated side effects, state boundaries are wrong.
  • The Context API is not just for global data — it is effective for isolating UI concerns.

Performance issues in React are often design issues in disguise.

Back to Blog

Related posts

Read more »