{"id":"jdevon/react-observable-value","name":"react-observable-value","scope":"jdevon","platform":"roblox","description":"React hooks for ObservableValue.","version":"0.1.0","latest":"0.1.0","versions":["0.1.0"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{"jdevon/observable-value":{"version":"^0.1.0","alias":"ObservableValue"},"jsdotlua/react":{"version":"^17.0.0","alias":"React"}},"integrity":"70b70cbab5139ddee66ec6aa2501834d1ac317f83d134b9f381ef6c013af284d","likes":0,"downloads":0,"install":"forest install jdevon/react-observable-value","url":"https://forest.dev/p/roblox/jdevon/react-observable-value","files":"https://api.forest.dev/ai/package/roblox/jdevon/react-observable-value/files","readme":"\n\n[react-observable-value/releases]: https://github.com/JDevon/react-observable-value/releases/latest\n[react-observable-value/wally]: https://wally.run/package/jdevon/react-observable-value\n\n\n\n[badges/github]: https://raw.githubusercontent.com/gist/cxmeel/0dbc95191f239b631c3874f4ccf114e2/raw/github.svg\n[badges/wally]: https://raw.githubusercontent.com/gist/cxmeel/0dbc95191f239b631c3874f4ccf114e2/raw/wally.svg\n\n# ReactObservableValue\n\nReact hooks for [ObservableValue](https://github.com/JDevon/observable-value): read a value and rerender, select part\nof it, or follow it with a binding.\n\nFull API reference at [jdevon.github.io/react-observable-value](https://jdevon.github.io/react-observable-value/).\n\n## Install\n\n[![badges/github]][react-observable-value/releases] [![badges/wally]][react-observable-value/wally]\n\nInstall with [Wally](https://wally.run) by adding both packages to your `wally.toml`:\n\n```toml\n[dependencies]\nObservableValue = \"jdevon/observable-value@0.1.0\"\nReactObservableValue = \"jdevon/react-observable-value@0.1.0\"\n```\n\nReactObservableValue only provides the hooks; you create values with ObservableValue. Wally installs a single copy\nof ObservableValue when both versions are compatible, so the hooks and your code share the same class.\n\n## Usage\n\n```lua\nlocal React = require(ReplicatedStorage.Packages.React)\nlocal ObservableValue = require(ReplicatedStorage.Packages.ObservableValue)\nlocal ReactObservableValue = require(ReplicatedStorage.Packages.ReactObservableValue)\n\nlocal health = ObservableValue.new(100)\n\nlocal function HealthLabel()\n\t-- rerenders whenever health changes\n\tlocal currentHealth = ReactObservableValue.useObservableValue(health)\n\n\treturn React.createElement(\"TextLabel\", {\n\t\tText = `{currentHealth} HP`,\n\t})\nend\n\nhealth:set(80) -- every mounted HealthLabel now shows 80 HP\n```\n\nThe second return value increases every time the value changes. Use it as a dependency when a table value may have\nbeen changed in place:\n\n```lua\nlocal inventory = ObservableValue.new({} :: { [string]: number })\n\nlocal function ItemCount()\n\tlocal items, updateId = ReactObservableValue.useObservableValue(inventory)\n\n\tlocal total = React.useMemo(function()\n\t\tlocal count = 0\n\t\tfor _, quantity in items do\n\t\t\tcount += quantity\n\t\tend\n\t\treturn count\n\tend, { updateId })\n\n\treturn React.createElement(\"TextLabel\", {\n\t\tText = `{total} items`,\n\t})\nend\n```\n\nFor values that change often, `useObservableBinding` follows the value with a React binding instead of rerendering:\n\n```lua\nlocal progress = ObservableValue.new(0)\n\nlocal function ProgressBar()\n\tlocal progressBinding = ReactObservableValue.useObservableBinding(progress)\n\n\treturn React.createElement(\"Frame\", {\n\t\tSize = progressBinding:map(function(value)\n\t\t\treturn UDim2.fromScale(value, 1)\n\t\tend),\n\t})\nend\n```\n\nTo rerender only when part of a value changes, `useObservableSelector` returns what your selector picks out:\n\n```lua\nlocal blurStack = ObservableValue.new({} :: { [number]: true })\n\nlocal function BlurOverlay()\n\t-- rerenders only when the stack goes from empty to not empty, or back\n\tlocal isVisible = ReactObservableValue.useObservableSelector(blurStack, function(stack)\n\t\treturn next(stack) ~= nil\n\tend)\n\n\treturn React.createElement(\"Frame\", {\n\t\tVisible = isVisible,\n\t})\nend\n```\n\nResults are compared with `==`. Pass an `isEqual` function as the third argument if your selector builds a new\ntable each time.\n\n## API\n\nEach member links to its full entry in the [API reference](https://jdevon.github.io/react-observable-value/api/ReactObservableValue).\n\n### Functions\n\n- [`.useObservableValue`](https://jdevon.github.io/react-observable-value/api/ReactObservableValue#useObservableValue) - returns an ObservableValue's current value and an update id, and rerenders the\n    component whenever the value changes.\n- [`.useObservableBinding`](https://jdevon.github.io/react-observable-value/api/ReactObservableValue#useObservableBinding) - returns a React binding that follows an ObservableValue without rerendering\n- [`.useObservableSelector`](https://jdevon.github.io/react-observable-value/api/ReactObservableValue#useObservableSelector) - returns part of an ObservableValue and rerenders only when that part changes\n","readmeTruncated":false}