{"_id":"signals-react-safe","_rev":"16-f08bc05af97d4211d25c25fb04535241","name":"signals-react-safe","dist-tags":{"latest":"1.2.0"},"versions":{"1.0.0":{"name":"signals-react-safe","version":"1.0.0","keywords":["react","signals","nextjs"],"author":{"name":"Jon Abrams"},"license":"MIT","_id":"signals-react-safe@1.0.0","maintainers":[{"name":"jonabrams","email":"jon@jonabrams.com"}],"homepage":"https://github.com/JonAbrams/signals-react-safe#readme","bugs":{"url":"https://github.com/JonAbrams/signals-react-safe/issues"},"dist":{"shasum":"34b57f3d8fb4a164bb6fec3ff161411bf218bfea","tarball":"https://registry.npmjs.org/signals-react-safe/-/signals-react-safe-1.0.0.tgz","fileCount":9,"integrity":"sha512-beyHF7apcRFnLyhpqB87RhDPOWHAIO1zFzXZkTpercmSA0bK0Eugdq5LLJnyvmjyjbQngOdetPDLl4UBJ6KUaA==","signatures":[{"sig":"MEUCIQC/agGz1Pqpchhu+7WNmX+va5CT7B+ew2mMgSrsDDGxGQIgdkmzn5zcwWDDdNP+ABHj5zdAZGN0BCWwO+Zo1K5GALA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17337},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","gitHead":"47314407a3fc96d73b863482c7a83a95335d8e09","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"tsup"},"_npmUser":{"name":"jonabrams","email":"jon@jonabrams.com"},"repository":{"url":"git+https://github.com/JonAbrams/signals-react-safe.git","type":"git"},"_npmVersion":"9.8.0","description":"A version of Preact Signals that integrates with React without touching React's internals. Allows Signals to be safely used with Next.js 13+'s App Router.","directories":{},"_nodeVersion":"19.8.1","dependencies":{"@preact/signals-core":"^1.5.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^7.2.0","typescript":"^5.2.2"},"peerDependencies":{"react":">=16.8","@types/react":">=16.8"},"_npmOperationalInternal":{"tmp":"tmp/signals-react-safe_1.0.0_1699211457321_0.16665101985925967","host":"s3://npm-registry-packages"}},"1.1.0":{"name":"signals-react-safe","version":"1.1.0","keywords":["react","signals","nextjs"],"author":{"name":"Jon Abrams"},"license":"MIT","_id":"signals-react-safe@1.1.0","maintainers":[{"name":"jonabrams","email":"jon@jonabrams.com"}],"homepage":"https://github.com/JonAbrams/signals-react-safe#readme","bugs":{"url":"https://github.com/JonAbrams/signals-react-safe/issues"},"dist":{"shasum":"14554ee964959b1b646126968f9c13dc92899055","tarball":"https://registry.npmjs.org/signals-react-safe/-/signals-react-safe-1.1.0.tgz","fileCount":9,"integrity":"sha512-bd5iKo/tCiTwZm+uP+c+2tWaguorbljZ/kaMXdD7zs2gsgJsuAvaMJ9nOj6XQ7tN7W5HBANcnCg1ETkNIPJUSQ==","signatures":[{"sig":"MEQCIEqPScvq5KGOPi+Mu3UZ9Ket5tuJOFJz8nwouhrpYzHiAiA36fg4xS0Xfga6zg0erhf2fv0dXI3IIw85Op7orR4S4g==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":18041},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","gitHead":"47314407a3fc96d73b863482c7a83a95335d8e09","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"tsup"},"_npmUser":{"name":"jonabrams","email":"jon@jonabrams.com"},"repository":{"url":"git+https://github.com/JonAbrams/signals-react-safe.git","type":"git"},"_npmVersion":"9.8.0","description":"A version of Preact Signals that integrates with React without touching React's internals. Allows Signals to be safely used with Next.js 13+'s App Router.","directories":{},"_nodeVersion":"19.8.1","dependencies":{"@preact/signals-core":"^1.5.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^7.2.0","typescript":"^5.2.2"},"peerDependencies":{"react":">=16.8","@types/react":">=16.8"},"_npmOperationalInternal":{"tmp":"tmp/signals-react-safe_1.1.0_1699213536382_0.8947592951150205","host":"s3://npm-registry-packages"}},"1.1.1":{"name":"signals-react-safe","version":"1.1.1","keywords":["react","signals","nextjs"],"author":{"name":"Jon Abrams"},"license":"MIT","_id":"signals-react-safe@1.1.1","maintainers":[{"name":"jonabrams","email":"jon@jonabrams.com"}],"homepage":"https://github.com/JonAbrams/signals-react-safe#readme","bugs":{"url":"https://github.com/JonAbrams/signals-react-safe/issues"},"dist":{"shasum":"9e2edecc7ce17778c6c5fd4b88d8de16391fc1bb","tarball":"https://registry.npmjs.org/signals-react-safe/-/signals-react-safe-1.1.1.tgz","fileCount":9,"integrity":"sha512-zDtaXFH2VIln+mXR5Q3ERNa8dTZy1XC8zM47NoMGPXHD28S5M0Wfl8apWEAAoNpNDBQ4oxy0p7250mUH7MaloA==","signatures":[{"sig":"MEUCIBG2LXOjb4nhMpMiGWXWdRHUlYsE9RLkYAQikk0iLVybAiEApY05zZJCgLewG0mC9+qsLS4gcnYjysugCA6g9zIt2+A=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":18569},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","gitHead":"ccc8f562df4a19ed6a3fac73acd8d692d0735f44","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"tsup"},"_npmUser":{"name":"jonabrams","email":"jon@jonabrams.com"},"repository":{"url":"git+https://github.com/JonAbrams/signals-react-safe.git","type":"git"},"_npmVersion":"9.8.0","description":"A version of Preact Signals that integrates with React without touching React's internals. Allows Signals to be safely used with Next.js 13+'s App Router.","directories":{},"_nodeVersion":"19.8.1","dependencies":{"@preact/signals-core":"^1.5.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^7.2.0","typescript":"^5.2.2"},"peerDependencies":{"react":">=16.8","@types/react":">=16.8"},"_npmOperationalInternal":{"tmp":"tmp/signals-react-safe_1.1.1_1699220930601_0.483198971172486","host":"s3://npm-registry-packages"}},"1.1.2":{"name":"signals-react-safe","version":"1.1.2","keywords":["react","signals","nextjs"],"author":{"name":"Jon Abrams"},"license":"MIT","_id":"signals-react-safe@1.1.2","maintainers":[{"name":"jonabrams","email":"jon@jonabrams.com"}],"homepage":"https://github.com/JonAbrams/signals-react-safe#readme","bugs":{"url":"https://github.com/JonAbrams/signals-react-safe/issues"},"dist":{"shasum":"13e1e08c00772e9c9bd93ab7dce937ee8617e454","tarball":"https://registry.npmjs.org/signals-react-safe/-/signals-react-safe-1.1.2.tgz","fileCount":9,"integrity":"sha512-SjMrxubsFFGW3g+ZBGtGkiE8N6h0srWm1znFs3KVG73sZPfQ6Gn6sHi/xy7lZMaGuoMjrBBEndO6YZwRs85n2Q==","signatures":[{"sig":"MEYCIQC/chUeGMeSYAyuQBE07DCbDft9qz6Cdy17jREX1QjvpgIhAOVQLnDtrs7WX18sJJcCfHqUvqsB8slFHURKCuJzQnbU","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":19433},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","gitHead":"476994d028bbf0d50a1e8ba0a10c17402b1ab73c","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"tsup"},"_npmUser":{"name":"jonabrams","email":"jon@jonabrams.com"},"repository":{"url":"git+https://github.com/JonAbrams/signals-react-safe.git","type":"git"},"_npmVersion":"9.8.0","description":"A version of Preact Signals that integrates with React without touching React's internals. Allows Signals to be safely used with Next.js 13+'s App Router.","directories":{},"_nodeVersion":"19.8.1","dependencies":{"@preact/signals-core":"^1.5.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^7.2.0","typescript":"^5.2.2","@types/react":">=16.8"},"peerDependencies":{"react":">=16.8"},"_npmOperationalInternal":{"tmp":"tmp/signals-react-safe_1.1.2_1699249628891_0.09492278862214154","host":"s3://npm-registry-packages"}},"1.2.0":{"name":"signals-react-safe","version":"1.2.0","description":"A version of Preact Signals that integrates with React without touching React's internals. Allows Signals to be safely used with Next.js 13+'s App Router.","main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","scripts":{"build":"tsup","test":"echo \"Error: no test specified\" && exit 1"},"repository":{"type":"git","url":"git+https://github.com/JonAbrams/signals-react-safe.git"},"keywords":["react","signals","nextjs"],"author":{"name":"Jon Abrams"},"license":"MIT","bugs":{"url":"https://github.com/JonAbrams/signals-react-safe/issues"},"homepage":"https://github.com/JonAbrams/signals-react-safe#readme","dependencies":{"@preact/signals-core":"^1.5.0"},"peerDependencies":{"react":">=16.8"},"devDependencies":{"@types/react":">=16.8","tsup":"^7.2.0","typescript":"^5.2.2"},"_id":"signals-react-safe@1.2.0","gitHead":"ce10b4328433556b18259b8e4aea14cf94b56a6c","_nodeVersion":"21.4.0","_npmVersion":"10.5.0","dist":{"integrity":"sha512-ABJxD9tEHeERBoKgYNDp2JJeiDAe16vVOO6mAhq6aR3C/O0PfqkGoUt9T9NvTzjIS7Lx7WaX8Ly5oCvZBzRozA==","shasum":"cd97a14c29ad46e0ed4433eb834362fbe88293d1","tarball":"https://registry.npmjs.org/signals-react-safe/-/signals-react-safe-1.2.0.tgz","fileCount":9,"unpackedSize":22472,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFmCCz2w43/IvI3cFHbDBWINmB5i8uhkd7KxM7HFukVNAiA3DyY62VD3L2dvL2MIfWDuUH8ZHxoAa4YBj2sa9UH74A=="}]},"_npmUser":{"name":"jonabrams","email":"jon@jonabrams.com"},"directories":{},"maintainers":[{"name":"jonabrams","email":"jon@jonabrams.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/signals-react-safe_1.2.0_1730945043085_0.04635319596720011"},"_hasShrinkwrap":false}},"time":{"created":"2023-11-05T19:10:57.320Z","modified":"2024-11-07T02:04:03.516Z","1.0.0":"2023-11-05T19:10:57.517Z","1.1.0":"2023-11-05T19:45:36.538Z","1.1.1":"2023-11-05T21:48:50.766Z","1.1.2":"2023-11-06T05:47:09.104Z","2.0.0-beta.1":"2023-12-21T07:11:10.428Z","2.0.0-beta.2":"2023-12-21T07:23:45.388Z","2.0.0-beta.3":"2023-12-21T07:24:51.562Z","2.0.0-beta.4":"2023-12-21T08:11:05.521Z","2.0.0-beta.5":"2023-12-21T08:14:01.902Z","2.0.0-beta.6":"2023-12-21T08:19:12.633Z","1.2.0":"2024-11-07T02:04:03.324Z"},"bugs":{"url":"https://github.com/JonAbrams/signals-react-safe/issues"},"author":{"name":"Jon Abrams"},"license":"MIT","homepage":"https://github.com/JonAbrams/signals-react-safe#readme","keywords":["react","signals","nextjs"],"repository":{"type":"git","url":"git+https://github.com/JonAbrams/signals-react-safe.git"},"description":"A version of Preact Signals that integrates with React without touching React's internals. Allows Signals to be safely used with Next.js 13+'s App Router.","maintainers":[{"name":"jonabrams","email":"jon@jonabrams.com"}],"readme":"# signals-react-safe\n\n[Signals]([@preact/signals](https://github.com/preactjs/signals)) is a state management library from the Preact team. This is a _safer_ alternative library.\n\nThe team provides a react compatibility library [signals-react](https://github.com/preactjs/signals/tree/main/packages/react), but it comes with a very large downside: It alters React's internals. This is a [big no-no](https://github.com/facebook/react/issues/26704#issuecomment-1522044060) for mainting compatibility with future versions of React, creating risk for your project. It also breaks compatibility with [Next.js](https://nextjs.org/), which is a pretty good and popular React framework.\n\nThis library still lets you get the biggest benefit of Signals. When you render a signal directly within your JSX/TSX it creates a text node that updates when the signal updates, skipping the re-render of the component you render it within.\n\nThis library provides [new hooks](#api) for reading the value of a signal in your React components. Instead of reading `mySignal.value` somewhere in your component, use `useSignalValue(mySignal)` instead.\n\nIMHO, this is also helps readibility since it makes it more clear what can cause a component to re-render, and works better with hooks such as useEffect.\n\n[Live editable demo](https://codesandbox.io/s/signals-react-safe-demo-jmcwst?file=/src/Counter.tsx)\n\n## Install\n\n```bash\nnpm install signals-react-safe\n```\n\n## Usage Example\n\n`mySignals.ts`\n\n```ts\nimport { signal } from 'signals-react-safe';\n\nexport const counter = signal(0);\n```\n\n`Counter.tsx` (this component does NOT re-render when the signal updates, which is more performant)\n\n```tsx\nimport { counter } from \"./mySignals\";\n\nexport function Counter() {\n  return (\n    <div>\n      <div>Current Count: {counter}</div>\n      <button onClick={() => counter.value++}>Add One</button>\n    </div>\n  );\n}\n```\n\n`MixedCounter.tsx` (this component does re-render when the signal updates, which allows the value to be combined with non-signal values)\n\n```tsx\nimport { useState } from \"react\";\nimport { counter } from \"./mySignals\";\n\nexport function MixedCounter() {\n  const counterValue = useSignalValue(counter);\n  const [myCounter, setMyCounter] = useState(0);\n\n  return (\n    <div>\n      <div>Summed: {counterValue + myCounter}</div>\n      <button onClick={() => counter.value++}>Add One to signal counter</button>\n      <button onClick={() => setMyCounter(myCounter + 1)}>\n        Add One to useState counter\n      </button>\n    </div>\n  );\n}\n```\n\n# API\n\nThis library provides a bunch of exported function:\n\n- Re-exports from the [core Signals library](https://github.com/preactjs/signals): `signal`, `computed`, `effect`.\n- Copy/pasted hooks from [@preact/signals-react](https://github.com/preactjs/signals/blob/main/packages/react): `useSignal`, `useComputed`, `useSignalEffect`.\n- New hooks unique to this library: `useSignalValue`, `useSignalAndValue`, `useComputedValue`.\n\n### `useSignalValue(signal)`\n\nTakes as input an existing signal, typically imported into your module from elsewhere in your app. If you want your component to create its own signal, use [`useSignal`](https://github.com/preactjs/signals/tree/main/packages/react#hooks) instead.\n\nIt returns the value stored in the signal. When the signal's value changes, this hook will trigger a component re-render and return the new value.\n\nUse this hook when you need to access the value stored in the signal, e.g. triggering a useEffect, or combining with non-signal values.\n\nIf you want to combine the value with other signal values, consider using `useComputed` or `useComputedValue` to be more performant.\n\nExample:\n```tsx\nimport {count} from '../signals';\nfunction Count() {\n  const countValue = useSignalValue(count);\n  useEffect(() => {\n    localStorage['count'] = `#{countValue}`;\n  }, [countValue]);\n  return <div>{count} <button onClick={() => count.value++}>Add one</button></div>\n}\n```\n\n### `useSignalAndValue`\n\nCreates a signal and returns it, along with its value. Triggers a component re-render in order to return the latest value. Use this to replace `useSignal` if you need to read the value of a component's signal within the component.\n\nIt returns an array with two elements:\n1. The signal.\n2. Its value.\n\nExample: \n```tsx\nfunction MyCounter() {\n  const [count, countValue] = useSignalAndValue(0);\n  useEffect(() => {\n    localStorage['count'] = `#{countValue}`;\n  }, [countValue]);\n  return <div>{count} <button onClick={() => count.value++}>Add one</button></div>;\n}\n```\n\n### `useComputedValue`\n\nTake a function as its parameter and returns a value. It's useful when that function uses multiple signals. \n\nA new value will be generated if any of the referenced signals are updated, causing the component to re-render.\n\nExample:\n```tsx\nimport {count} from '../signals';\nfunction MyMultiplier() {\n  const multiplier = useSignal(1);\n  const multipliedValue = useComputedValue(() => multiplier.value * count.value);\n  useEffect(() => {\n    localStorage['multiplied'] = `#{multipliedValue}`;\n  }, [countValue]);\n  return <div>{multiplier} <button onClick={() => multiplier.value++}>Add one</button></div>;\n}\n```\n\n# Performance\n\nThe new hooks that directly return values will trigger re-renders of the component. This would also happen if you read a signal's value inside a component when using [@preact/signals-react](https://github.com/preactjs/signals/tree/main/packages/react). If you want to avoid that re-render, place your signal directly in your JSX.\n\n# Author\n\nCreated by [Jon Abrams](https://threads.net/jon.abrams) (2023)\n\n# Attributions\n\nContains code from [Preact Signals](https://github.com/preactjs/signals)\n\nIdea inspired by [satoshi-cyber](https://github.com/satoshi-cyber)'s [suggestion](https://github.com/vercel/next.js/issues/45054#issuecomment-1694791734).\n","readmeFilename":"README.md"}