Meeshan.dev
Shadcn RegistryLib

Scope Provider

A lightweight wrapper around React Context that makes passing values down your component tree a lot easier.

Installation

pnpm dlx shadcn add https://meeshan.dev/r/scope-provider.json

Why do you need this?

In React apps, passing data through many levels of components can quickly turn into "prop drilling" — where you're passing props through components that don't even need them just to get them to where they're actually used. It's a mess to maintain and even harder to read.

I built ScopeProvider and useScopeCtx to fix this. They use React's Context API under the hood to let your components access shared data without all that annoying prop drilling.

Sure, you could use React's built-in Context API directly, but it usually involves a bit of boilerplate to set up. I've simplified the whole process with a straightforward API for creating providers, and useScopeCtx makes it a breeze to grab the context value anywhere within the provider's scope.

API

ScopeProvider

This wraps your children with a context provider.

import { ScopeProvider } from '~/lib/scope-provider';

function App() {
  const [state, setState] = useState<MyType>(initialValue);

  return (
    <ScopeProvider value={{ state, setState }}>
      <Dashboard />
    </ScopeProvider>
  );
}

Props

PropTypeDescription
valueunknownThe value to provide to consumers.
childrenReact.ReactNodeThe component subtree.

useScopeCtx

This is how you consume the value from the nearest ScopeProvider.

import { useScopeCtx } from '~/lib/scope-provider';

function Dashboard() {
  const { state } = useScopeCtx<MyType>();

  return <p>Welcome, {state.someProp}..!</p>;
}

Options

OptionTypeDefaultDescription
shouldThrowbooleantrueWhether to throw an error if no provider is found. Returns null if used outside a provider and shouldThrow is false.

Usage Examples

Optional Context

If you want the provider to be optional, just set shouldThrow: false:

function OptionalConsumer() {
  const ctx = useScopeCtx<{ theme: string }>({ shouldThrow: false });

  const theme = ctx?.theme ?? 'light';

  return <div>Theme: {theme}</div>;
}

On this page