{"_id":"@dmrk/use-context-with-selectors","_rev":"6-bd2e1230717796107af6c1f75b39261d","name":"@dmrk/use-context-with-selectors","dist-tags":{"latest":"0.0.5"},"versions":{"0.0.1":{"name":"@dmrk/use-context-with-selectors","version":"0.0.1","keywords":[],"author":"","license":"ISC","_id":"@dmrk/use-context-with-selectors@0.0.1","maintainers":[{"name":"dmarushchak","email":"denismar322@gmail.com"}],"dist":{"shasum":"43d151427c911760fe841f23073518dcf5aeafdd","tarball":"https://registry.npmjs.org/@dmrk/use-context-with-selectors/-/use-context-with-selectors-0.0.1.tgz","fileCount":10,"integrity":"sha512-kwZXGI/6UNSQFJIF2KIROuPftaUqIL6CiARKVWemJkMgs9za00xEy6dZqvi4gVxY09VjxriUHmOUxfkcKqUwKA==","signatures":[{"sig":"MEUCIQDclDM8fJoxAAuL27BUUMUesQk7mBMnsOH5wjhe3lICsgIgJDFqga3ozCxtwUCwJ+aIy/KxJAhDjbWliGV5cF/u5zM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":22960},"main":"index.js","gitHead":"301a7eb4dd45b8ec6b47b7a46e9fd3d06e03c6eb","scripts":{"test":"vitest","build":"rollup -c","watch":"rollup -c -w"},"_npmUser":{"name":"dmarushchak","email":"denismar322@gmail.com"},"_npmVersion":"10.9.2","description":"A lightweight React library for creating context with fine-grained selector-based subscriptions, preventing unnecessary re-renders.","directories":{},"_nodeVersion":"23.10.0","_hasShrinkwrap":false,"devDependencies":{"react":"^19.2.0","tslib":"^2.8.1","rollup":"^4.52.5","vitest":"^4.0.7","happy-dom":"^20.0.10","react-dom":"^19.2.0","typescript":"^5.9.3","@types/react":"^19.2.2","@testing-library/react":"^16.3.0","rollup-plugin-typescript2":"^0.36.0","@rollup/plugin-node-resolve":"^16.0.3"},"peerDependencies":{"react":"^18.0.0","react-dom":"^18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/use-context-with-selectors_0.0.1_1762496477621_0.12788695292692354","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Package no longer supported. Contact Support at https://www.npmjs.com/support for more info."},"0.0.2":{"name":"@dmrk/use-context-with-selectors","version":"0.0.2","keywords":[],"author":"","license":"ISC","_id":"@dmrk/use-context-with-selectors@0.0.2","maintainers":[{"name":"dmarushchak","email":"denismar322@gmail.com"}],"dist":{"shasum":"345b0049b4b515331df675199b5c32b49fd9c413","tarball":"https://registry.npmjs.org/@dmrk/use-context-with-selectors/-/use-context-with-selectors-0.0.2.tgz","fileCount":10,"integrity":"sha512-ivqpd1ic94Q1eDizyBCbJsRiPvP78udR8INVV3YWmtzAeOCCTEWOqOXPMJuznszcVSBsmdLcsjDxOZ/2YyWnQA==","signatures":[{"sig":"MEYCIQCSVEVv4lkS9Td+bkeCkMSo8O3FEQTwZydH4KpIuu/JjgIhAPSNZWrHnIWxavHxvyUncxKZF3KfY+aDIvUhhxpcseij","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":22962},"main":"index.js","gitHead":"6401eeaa87c934205b12403215265aa1efc17c90","scripts":{"test":"vitest","build":"rollup -c","watch":"rollup -c -w"},"_npmUser":{"name":"dmarushchak","email":"denismar322@gmail.com"},"_npmVersion":"10.9.2","description":"A lightweight React library for creating context with fine-grained selector-based subscriptions, preventing unnecessary re-renders.","directories":{},"_nodeVersion":"23.10.0","_hasShrinkwrap":false,"devDependencies":{"react":"^19.2.0","tslib":"^2.8.1","rollup":"^4.52.5","vitest":"^4.0.7","happy-dom":"^20.0.10","react-dom":"^19.2.0","typescript":"^5.9.3","@types/react":"^19.2.2","@testing-library/react":"^16.3.0","rollup-plugin-typescript2":"^0.36.0","@rollup/plugin-node-resolve":"^16.0.3"},"peerDependencies":{"react":">=18.0.0","react-dom":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/use-context-with-selectors_0.0.2_1762496745423_0.1502995062698571","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Package no longer supported. Contact Support at https://www.npmjs.com/support for more info."},"0.0.3":{"name":"@dmrk/use-context-with-selectors","version":"0.0.3","keywords":["react","context","selectors"],"author":{"name":"Denis Marushchak"},"license":"ISC","_id":"@dmrk/use-context-with-selectors@0.0.3","maintainers":[{"name":"dmarushchak","email":"denismar322@gmail.com"}],"dist":{"shasum":"511fb1fd29c3862690cf531ab663c7e96b05a5d6","tarball":"https://registry.npmjs.org/@dmrk/use-context-with-selectors/-/use-context-with-selectors-0.0.3.tgz","fileCount":7,"integrity":"sha512-DwMCM0KJkgM/1rwLfxPnjEuM58HIz+Zl/Twl/tJLO401k6azfQLHLe4D2MHJtE/0caa/F+ve2ESmTIgNREj9tw==","signatures":[{"sig":"MEQCIAfCBnmifnzG6baZDHDKjuUN4rs4bUGT0QdJdHUvzTr3AiAOauDS80BQt4h1Y6T2YAxb9F5D76+Go7JWGjMpa/QdBw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":18599},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"bd1a25e4bed33c41eb2935150819c2fd36b063c1","scripts":{"test":"vitest","build":"rollup -c","watch":"rollup -c -w"},"_npmUser":{"name":"dmarushchak","email":"denismar322@gmail.com"},"_npmVersion":"10.9.2","description":"A library for using context with selectors","directories":{},"_nodeVersion":"23.10.0","_hasShrinkwrap":false,"devDependencies":{"tslib":"^2.8.1","rollup":"^4.52.5","vitest":"^4.0.7","happy-dom":"^20.0.10","typescript":"^5.9.3","@types/react":"^19.2.2","@testing-library/react":"^16.3.0","rollup-plugin-typescript2":"^0.36.0","@rollup/plugin-node-resolve":"^16.0.3"},"peerDependencies":{"react":">=18.0.0","react-dom":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/use-context-with-selectors_0.0.3_1762497016240_0.9974716362782321","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Package no longer supported. Contact Support at https://www.npmjs.com/support for more info."},"0.0.4":{"name":"@dmrk/use-context-with-selectors","version":"0.0.4","keywords":["react","context","selectors"],"author":{"name":"Denis Marushchak"},"license":"ISC","_id":"@dmrk/use-context-with-selectors@0.0.4","maintainers":[{"name":"dmarushchak","email":"denismar322@gmail.com"}],"dist":{"shasum":"6bed8cc91305c9606696f8486f7e6da5f2e78f9b","tarball":"https://registry.npmjs.org/@dmrk/use-context-with-selectors/-/use-context-with-selectors-0.0.4.tgz","fileCount":9,"integrity":"sha512-skmxXMgkTtIUK1xCqKVfWlTfdfnErcLroYkPwDSnX3gzfsLnSutRQqMmAH9arhm4LheeFiNKf3ZSs6xQy9hG0w==","signatures":[{"sig":"MEUCIDp4BfW7iK1Ivg0c7alD9Q35dTf1bLewMWfojPA0635zAiEA0DxYU2A/hHqTJN6/+M4UNtocgV/XRH/420Swyu2B+bI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":13262},"main":"dist/index.js","_from":"file:dmrk-use-context-with-selectors-0.0.4.tgz","types":"dist/index.d.ts","scripts":{"test":"vitest","build":"rollup -c","watch":"rollup -c -w"},"_npmUser":{"name":"dmarushchak","email":"denismar322@gmail.com"},"_resolved":"/tmp/327b6ffcfe679509879e073579bd47e5/dmrk-use-context-with-selectors-0.0.4.tgz","_integrity":"sha512-skmxXMgkTtIUK1xCqKVfWlTfdfnErcLroYkPwDSnX3gzfsLnSutRQqMmAH9arhm4LheeFiNKf3ZSs6xQy9hG0w==","_npmVersion":"10.8.2","description":"A library for using context with selectors","directories":{},"_nodeVersion":"18.20.8","_hasShrinkwrap":false,"devDependencies":{"tslib":"^2.8.1","rollup":"^4.52.5","vitest":"^4.0.7","happy-dom":"^20.0.10","typescript":"^5.9.3","@types/react":"^19.2.2","@dmrk/vitest-config":"^0.0.0","@testing-library/react":"^16.3.0","@dmrk/typescript-config":"^0.0.0","rollup-plugin-typescript2":"^0.36.0","@rollup/plugin-node-resolve":"^16.0.3"},"peerDependencies":{"react":">=18.0.0","react-dom":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/use-context-with-selectors_0.0.4_1762521479038_0.6874836036453171","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Package no longer supported. Contact Support at https://www.npmjs.com/support for more info."},"0.0.5":{"name":"@dmrk/use-context-with-selectors","version":"0.0.5","keywords":["react","context","selectors"],"author":{"name":"Denis Marushchak"},"license":"ISC","_id":"@dmrk/use-context-with-selectors@0.0.5","maintainers":[{"name":"dmarushchak","email":"denismar322@gmail.com"}],"dist":{"shasum":"2a92c9c1eee186c714d83458a9526f854d9a3e9a","tarball":"https://registry.npmjs.org/@dmrk/use-context-with-selectors/-/use-context-with-selectors-0.0.5.tgz","fileCount":9,"integrity":"sha512-7N9QKo9IFNnLt8Cugc52Qk1Rhp3hpMKctodiVAYV/uf1n5Z1NnPEdS3UswbcVpezDD5stqzdSpL+WfRCrTwMMA==","signatures":[{"sig":"MEUCICZDgDICbykWik+EsGwqYC+eXpXR2yQizAP3uibS2jKWAiEAptdgmeE5nnd9Tn4bDc94FIgvkCWqGXhXdHdtWZdZVSM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":13227},"main":"dist/index.js","_from":"file:dmrk-use-context-with-selectors-0.0.5.tgz","types":"dist/index.d.ts","scripts":{"test":"vitest","build":"rollup -c","watch":"rollup -c -w"},"_npmUser":{"name":"dmarushchak","email":"denismar322@gmail.com"},"_resolved":"/tmp/c8f5ace4d5aeaae19edb66e7d9cb7720/dmrk-use-context-with-selectors-0.0.5.tgz","_integrity":"sha512-7N9QKo9IFNnLt8Cugc52Qk1Rhp3hpMKctodiVAYV/uf1n5Z1NnPEdS3UswbcVpezDD5stqzdSpL+WfRCrTwMMA==","_npmVersion":"10.8.2","description":"A library for using context with selectors","directories":{},"_nodeVersion":"18.20.8","_hasShrinkwrap":false,"devDependencies":{"tslib":"^2.8.1","rollup":"^4.52.5","vitest":"^4.0.7","happy-dom":"^20.0.10","typescript":"^5.9.3","@types/react":"^19.2.2","@dmrk/vitest-config":"^0.0.0","@testing-library/react":"^16.3.0","@dmrk/typescript-config":"^0.0.0","rollup-plugin-typescript2":"^0.36.0","@rollup/plugin-node-resolve":"^16.0.3"},"peerDependencies":{"react":">=18.0.0","react-dom":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/use-context-with-selectors_0.0.5_1762521974063_0.21143108480778716","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Package no longer supported. Contact Support at https://www.npmjs.com/support for more info."}},"time":{"created":"2025-11-07T06:21:17.526Z","modified":"2025-11-10T09:38:10.349Z","0.0.1":"2025-11-07T06:21:17.800Z","0.0.2":"2025-11-07T06:25:45.609Z","0.0.3":"2025-11-07T06:30:16.451Z","0.0.4":"2025-11-07T13:17:59.239Z","0.0.5":"2025-11-07T13:26:14.269Z"},"author":{"name":"Denis Marushchak"},"license":"ISC","keywords":["react","context","selectors"],"description":"A library for using context with selectors","maintainers":[{"name":"dmarushchak","email":"denismar322@gmail.com"}],"readme":"# use-context-with-selectors\n\nA lightweight React library for creating context with fine-grained selector-based subscriptions, preventing unnecessary re-renders.\n\n## Features\n\n- 🎯 **Selector-based subscriptions** - Components only re-render when their selected values change\n- ⚡ **Performance optimized** - Uses `useSyncExternalStore` for efficient updates\n- 🔒 **Type-safe** - Full TypeScript support with type inference\n- 🪶 **Lightweight** - Minimal dependencies, small bundle size\n- 🎨 **Simple API** - Easy to use with familiar React patterns\n\n## Installation\n\n```bash\npnpm add @dmrk/use-context-with-selectors\n```\n\n## Quick Start\n\n```tsx\nimport {\n  createContextWithSelectors,\n  createContextHook,\n} from '@dmrk/use-context-with-selectors';\n\n// 1. Create your store\nconst store = createContextWithSelectors({\n  count: 0,\n  name: 'John',\n});\n\n// 2. Create a custom hook (optional but recommended)\nconst useStore = createContextHook(store);\n\n// 3. Wrap your app with the Provider\nfunction App() {\n  return (\n    <store.Provider>\n      <Counter />\n      <Name />\n    </store.Provider>\n  );\n}\n\n// 4. Use selectors in your components\nfunction Counter() {\n  // This component only re-renders when count changes\n  const count = useStore(state => state.count);\n\n  return (\n    <div>\n      <p>Count: {count}</p>\n      <button onClick={() => store.set({ count: count + 1 })}>Increment</button>\n    </div>\n  );\n}\n\nfunction Name() {\n  // This component only re-renders when name changes\n  const name = useStore(state => state.name);\n\n  return <p>Name: {name}</p>;\n}\n```\n\n## API Reference\n\n### `createContextWithSelectors<State>(initialValue)`\n\nCreates a new context store with the given initial state.\n\n**Parameters:**\n\n- `initialValue`: The initial state object\n\n**Returns:**\nAn object containing:\n\n- `Provider`: React component to wrap your app\n- `context`: The React context (for advanced usage)\n- `get()`: Function to get current state\n- `set(partial)`: Function to update state\n- `value`: The store value (for advanced usage)\n\n**Example:**\n\n```tsx\nconst store = createContextWithSelectors({\n  user: { name: 'Alice', age: 25 },\n  theme: 'dark',\n});\n```\n\n### `createContextHook(store)`\n\nCreates a custom hook for the given store with a cleaner API.\n\n**Parameters:**\n\n- `store`: A store created by `createContextWithSelectors`\n\n**Returns:**\nA hook function that accepts a selector\n\n**Example:**\n\n```tsx\nconst useStore = createContextHook(store);\n\nfunction MyComponent() {\n  const userName = useStore(state => state.user.name);\n  return <div>{userName}</div>;\n}\n```\n\n### `useContextWithSelectors(context, selector)`\n\nLow-level hook for using context with selectors. Use `createContextHook` for a better API.\n\n**Parameters:**\n\n- `context`: The React context from the store\n- `selector`: Function to select a value from state\n\n**Returns:**\nThe selected value\n\n**Example:**\n\n```tsx\nfunction MyComponent() {\n  const count = useContextWithSelectors(store.context, state => state.count);\n  return <div>{count}</div>;\n}\n```\n\n## Advanced Usage\n\n### Derived Values\n\nYou can compute derived values in your selectors:\n\n```tsx\nconst useStore = createContextHook(store);\n\nfunction DoubledCounter() {\n  const doubled = useStore(state => state.count * 2);\n  return <div>Doubled: {doubled}</div>;\n}\n```\n\n### Complex Selectors\n\nSelect nested values or combine multiple values:\n\n```tsx\nconst store = createContextWithSelectors({\n  user: { name: 'Alice', age: 25 },\n  settings: { theme: 'dark', language: 'en' },\n});\n\nconst useStore = createContextHook(store);\n\nfunction UserInfo() {\n  const userAge = useStore(state => state.user.age);\n  const theme = useStore(state => state.settings.theme);\n\n  return <div className={theme}>User age: {userAge}</div>;\n}\n```\n\n### Updating State\n\nUpdate state using the `set` method:\n\n```tsx\n// Partial updates - only updates specified fields\nstore.set({ count: 10 });\n\n// Update nested objects\nstore.set({\n  user: { ...store.get().user, age: 26 },\n});\n\n// Update from component\nfunction UpdateButton() {\n  const count = useStore(state => state.count);\n\n  return (\n    <button onClick={() => store.set({ count: count + 1 })}>Increment</button>\n  );\n}\n```\n\n### Direct State Access\n\nAccess state directly without subscribing:\n\n```tsx\n// Get current state\nconst currentState = store.get();\n\n// Useful for event handlers or effects\nfunction handleClick() {\n  const current = store.get();\n  console.log('Current count:', current.count);\n  store.set({ count: current.count + 1 });\n}\n```\n\n## Performance Benefits\n\nComponents only re-render when their selected values change:\n\n```tsx\nconst store = createContextWithSelectors({\n  count: 0,\n  name: 'John',\n});\n\nconst useStore = createContextHook(store);\n\nfunction Counter() {\n  const count = useStore(state => state.count);\n  // ✅ Only re-renders when count changes\n  return <div>{count}</div>;\n}\n\nfunction Name() {\n  const name = useStore(state => state.name);\n  // ✅ Only re-renders when name changes\n  return <div>{name}</div>;\n}\n\n// When you update count:\nstore.set({ count: 1 });\n// ✅ Only Counter re-renders, Name does not!\n```\n\n## TypeScript Support\n\nFull type inference and type safety:\n\n```tsx\ntype AppState = {\n  user: { name: string; age: number };\n  count: number;\n};\n\nconst store = createContextWithSelectors<AppState>({\n  user: { name: 'Alice', age: 25 },\n  count: 0,\n});\n\nconst useStore = createContextHook(store);\n\nfunction MyComponent() {\n  // ✅ TypeScript knows the return type\n  const userName = useStore(state => state.user.name); // string\n  const count = useStore(state => state.count); // number\n\n  // ❌ TypeScript error - invalid property\n  // const invalid = useStore(state => state.invalid);\n\n  return <div>{userName}</div>;\n}\n```\n\n## Comparison with Other Solutions\n\n### vs React Context + useContext\n\n**Standard Context:**\n\n- ❌ All consumers re-render on any state change\n- ❌ Requires manual optimization with useMemo/memo\n- ✅ Built into React\n\n**use-context-with-selectors:**\n\n- ✅ Only re-renders when selected values change\n- ✅ Automatic optimization\n- ✅ Simpler API for complex state\n\n### vs Zustand\n\n**Zustand:**\n\n- ✅ More features (middleware, devtools, etc.)\n- ✅ Can be used outside React\n- ❌ Larger bundle size\n- ❌ More complex API\n\n**use-context-with-selectors:**\n\n- ✅ Smaller bundle size\n- ✅ Simpler API\n- ✅ Better for React-only projects\n- ❌ Fewer features (for now)\n\n## Requirements\n\n- React 18.0.0 or higher (requires `useSyncExternalStore` support or polyfill)\n\n## License\n\nISC\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## Author\n\ndmrk\n","readmeFilename":"README.md"}