npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-ctx-selector

v0.1.5

Published

A lightweight React utility that provides a real context selector hook. Unlike useContext, it lets components subscribe to only the part of context they need, avoiding unnecessary re-renders for better performance.

Readme

React Context Selector

A lightweight React utility that provides a real context selector hook. Unlike useContext, it lets components subscribe to only the part of context they need, avoiding unnecessary re-renders for better performance.

Why choose this over use-context-selector? This package provides true re-render prevention by using deep equality comparison (react-fast-compare) instead of Object.is, ensuring components only re-render when their selected data actually changes.


Getting Started

Start by installing the package via your preferred package manager:

npm install react-ctx-selector

or, if using pnpm:

pnpm add react-ctx-selector

☕ 60-Second TL;DR

Show a minimal but practical example that someone can copy-paste to immediately see results:

import { createContext, useContextSelector } from 'react-ctx-selector';

const MyContext = createContext({ name: 'John', age: 25 });

export default function Demo() {
  // Only re-renders when 'name' changes, not when 'age' changes
  const name = useContextSelector(MyContext, (state) => state.name);
  return <div>Hello, {name}!</div>;
}

Usage

Provide a more detailed usage example:

import { createContext, useContextSelector } from 'react-ctx-selector';
import { useState } from 'react';

const MyContext = createContext({ name: 'John', age: 25 });

function Provider() {
  const [state, setState] = useState({ name: 'John', age: 25 });

  return <MyContext.Provider value={[state, setState]}>{children}</MyContext.Provider>;
}

function ComponentName() {
  // Only re-renders when 'name' changes, not when 'age' changes
  const name = useContextSelector(MyContext, (context) => context[0].name);
  return <div>Hello, {name}!</div>;
}

function ComponentAge() {
  // Only re-renders when 'name' changes, not when 'age' changes
  const age = useContextSelector(MyContext, (context) => context[0].name);
  return <div>You are, {age} old!</div>;
}

function Changer() {
  const set = useContextSelector(MyContext, (context) => context[1]);

  return (
    <>
      <button onClick={() => set(prev => ({...prev, name:prev.name+"-new"}))}>Change Name</button>
      <button onClick={() => set(prev => ({...prev, age:prev.age+1}))}>Increment Age</button>
    </>
  )
}

export default function Demo() {
  return (
    <Provider>
      <ComponentName />
      <ComponentAge />
      <Changer />
      {/* the rest ...*/}
    </Provider>
  )
}

API Reference

Function createContext(initialValue)

Creates a context with selector capabilities that prevents unnecessary re-renders.

Parameters:

| Parameter | Type | Description | |----------------|------|------------------------------------| | initialValue | any | The initial value for the context. |

Returns:

  • Type: MyContextType<V>
  • An object containing Provider component and MyContext for advanced usage.

Example:

import { createContext } from 'react-ctx-selector';

const MyContext = createContext({ count: 0, name: 'Initial' });

Function useContextSelector(context, selector?, compareUsing?)

Hook that subscribes to a specific part of context, preventing re-renders when unselected parts change.

Parameters:

| Parameter | Type | Description | |----------------|----------------------------|-----------------------------------------------------| | context | MyContextType | Context created with createContext | | selector | (value: V) => T (optional) | Function to select specific part of context | | compareUsing | (a: T, b: T) => boolean | Custom comparison function (defaults to deep equal) |

Returns:

  • Type: T (selected value type)
  • The selected value from context that will trigger re-renders only when it changes.

Example:

import { useContextSelector } from 'react-ctx-selector';

// Select entire context
const fullState = useContextSelector(MyContext);

// Select specific property
const count = useContextSelector(MyContext, (state) => state.count);

// Custom comparison
const user = useContextSelector(
  MyContext, 
  (state) => state.user,
  (a, b) => a.id === b.id // Only re-render if user ID changes
);

Function useContext(context)

Alternative hook that selects the entire context value (equivalent to useContextSelector without a selector).

Parameters:

| Parameter | Type | Description | |-----------|------------------|--------------------------------------| | context | MyContextType | Context created with createContext |

Returns:

  • Type: V
  • The complete context value.

Example:

import { useContext } from 'react-ctx-selector';

const entireContext = useContext(MyContext);

🎯 Best Practices

Separate Provider State to Prevent Children Re-renders

Important: To maximize performance and prevent unnecessary re-renders of all children, it's recommended to separate the Provider component and its state management into different components.

❌ Not Recommended - Provider with inline state

function App() {
  const [state, setState] = useState({ name: 'John', age: 25 });
  
  return (
    <MyContext.Provider value={[state, setState]}>
      <ChildComponent1 />
      <ChildComponent2 />
      <ChildComponent3 />
      {/* All these children will re-render when App re-renders */}
    </MyContext.Provider>
  );
}

✅ Recommended - Separated Provider Component

// Separate Provider component
function MyProvider({ children }) {
  const [state, setState] = useState({ name: 'John', age: 25 });
  
  return (
    <MyContext.Provider value={[state, setState]}>
      {children}
    </MyContext.Provider>
  );
}

// Main App component
function App() {
  // This component can re-render without affecting the context children
  return (
    <MyProvider>
      <ChildComponent1 />
      <ChildComponent2 />
      <ChildComponent3 />
      {/* These children won't re-render when App re-renders */}
    </MyProvider>
  );
}

Why this matters:

  • When the Provider's state is managed in the same component as other UI logic, any re-render of that component will also re-render all Provider children
  • By separating the Provider into its own component, you isolate the context state management from other rendering triggers
  • This pattern works perfectly with useContextSelector to provide maximum performance optimization

❓ FAQ

How is this different from use-context-selector? This package uses deep equality comparison (react-fast-compare) instead of Object.is, providing true re-render prevention when context values are objects or arrays that may be recreated but contain the same data.

Can I use custom comparison functions? Yes! The useContextSelector hook accepts a third parameter compareUsing where you can provide your own comparison logic.

Does this work with Server-Side Rendering (SSR)? Yes, the package uses useSyncExternalStore with proper server-side snapshot handling to ensure SSR compatibility.

What's the performance impact? Minimal. The package uses efficient subscription patterns and only runs comparisons when the context value changes, not on every render.

Issues

If you encounter any issue, please open an issue here.

License

Distributed under the MIT License. See LICENSE file for more details.

© 2025 Hichem Taboukouyout


If you found this package helpful, consider leaving a star! ⭐️