{"id":13862892,"url":"https://github.com/dioxus-community/dioxus-radio","last_synced_at":"2025-06-17T00:39:00.281Z","repository":{"id":212083671,"uuid":"730429803","full_name":"dioxus-community/dioxus-radio","owner":"dioxus-community","description":"Fully-typed global state management with a topics subscription system for Dioxus 🧬","archived":false,"fork":false,"pushed_at":"2025-05-24T10:57:45.000Z","size":236,"stargazers_count":56,"open_issues_count":1,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-24T11:37:00.523Z","etag":null,"topics":["dioxus","rust","state-management"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dioxus-community.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-12-11T22:55:17.000Z","updated_at":"2025-05-23T12:01:37.000Z","dependencies_parsed_at":"2025-05-24T11:29:39.438Z","dependency_job_id":"51ce9882-dd9e-480f-929c-57b267cacab9","html_url":"https://github.com/dioxus-community/dioxus-radio","commit_stats":null,"previous_names":["dioxus-community/dioxus-radio"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/dioxus-community/dioxus-radio","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dioxus-community%2Fdioxus-radio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dioxus-community%2Fdioxus-radio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dioxus-community%2Fdioxus-radio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dioxus-community%2Fdioxus-radio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dioxus-community","download_url":"https://codeload.github.com/dioxus-community/dioxus-radio/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dioxus-community%2Fdioxus-radio/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260268635,"owners_count":22983601,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dioxus","rust","state-management"],"created_at":"2024-08-05T06:01:55.203Z","updated_at":"2025-06-17T00:39:00.269Z","avatar_url":"https://github.com/dioxus-community.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"[![Discord Server](https://img.shields.io/discord/899851952891002890.svg?logo=discord\u0026style=flat-square)](https://discord.gg/sKJSVNSCDJ)\r\n\r\n# dioxus-radio 📡🦀\r\n\r\n**Fully-typed global state management with a topics subscription system** for [Dioxus 🧬](https://dioxuslabs.com/).\r\n\r\n## Who is this for\r\n- You want a global state with nested reactivity\r\n- You really don't want unnecessary re-runs\r\n- You want a precise state subscription system\r\n- You don't want to clone the state unnecessarily\r\n\r\n## Support\r\n\r\n- **Dioxus v0.6** 🧬\r\n- All renderers ([web](https://dioxuslabs.com/learn/0.6/getting_started/wasm), [desktop](https://dioxuslabs.com/learn/0.6/getting_started/desktop), [freya](https://github.com/marc2332/freya), etc)\r\n- Both WASM and native targets\r\n\r\n## Questions\r\n\r\nFeel free to open a discussions in the [Discussions tab](https://github.com/dioxus-community/dioxus-radio/discussions).\r\n\r\n## Installation\r\nInstall the latest release:\r\n```sh\r\ncargo add dioxus-radio\r\n```\r\n\r\n## Example\r\n\r\n```bash\t\r\ncargo run --example demo\r\n```\r\n\r\n## Problem\r\n\r\nYou have a single global state but your components end up rerunning unnecessarily because even though the state itself has changed, not all components are interested in the new mutated state. Instead, you want a global state with nested reactivity.\r\n\r\nOther frameworks solve this in their own way, for instance, Solid and its [Stores](https://www.solidjs.com/tutorial/stores_createstore) allow you to mutate the state granularly by requiring you to specify the path to the part of the state you want to mutate, this allows Solid to then rerender components that are reading from that specific part of the State.\r\n\r\nThis doesn't translate well to rust neither Dioxus, but luckily, there are other ways.\r\n\r\n`dioxus-radio` presents a different approach, in order to have granular subscription with a global state you indicate a `Channel`, this way, whenever you mutate the state only other subscribers of the same `Channel` will be notified. This particular pattern translates quite well to Rust thanks to the usage of en Enums as `Channel`s.\r\n\r\n## Example\r\n\r\nLet's imagine we want an app where there might be `N` elements with each one having it's own state, at first you might think of simply using local signals in each component instance. But there is a constraint to this example, the state must be global so other components can read the state of those `N` elements.\r\n\r\nHere is an example:\r\n\r\n```rs\r\n\r\n// Global state\r\n#[derive(Default)]\r\nstruct Data {\r\n    pub lists: Vec\u003cVec\u003cString\u003e\u003e,\r\n}\r\n\r\n// Channels used to identify the subscribers of the State\r\n#[derive(PartialEq, Eq, Clone, Debug, Copy, Hash)]\r\npub enum DataChannel {\r\n    ListCreation,\r\n    SpecificListItemUpdate(usize),\r\n}\r\n\r\nimpl RadioChannel\u003cData\u003e for DataChannel {}\r\n\r\nfn main() {\r\n    dioxus::launch(|| {\r\n        // Initialize the global state\r\n        use_init_radio_station::\u003cData, DataChannel\u003e(Data::default);\r\n        // Subscribe to the state with the channel `DataChannel::ListCreation`\r\n        // This way whenever a writer using the `DataChannel::ListCreation` mutates the state\r\n        // This component will rerun\r\n        let mut radio = use_radio::\u003cData, DataChannel\u003e(DataChannel::ListCreation);\r\n\r\n        let onclick = move |_| {\r\n            radio.write().lists.push(Vec::default());\r\n        };\r\n\r\n        println!(\"Running DataChannel::ListCreation\");\r\n\r\n        rsx!(\r\n            button {\r\n                onclick,\r\n                \"Add new list\",\r\n            }\r\n            for (list_n, _) in radio.read().lists.iter().enumerate() {\r\n                ListComp {\r\n                    key: \"{list_n}\",\r\n                    list_n\r\n                }\r\n            }\r\n        )\r\n    });\r\n}\r\n\r\n#[allow(non_snake_case)]\r\n#[component]\r\nfn ListComp(list_n: usize) -\u003e Element {\r\n    // Subscribe the state using the `DataChannel::SpecificListItemUpdate(list_n)` channel, where `list_n` is index of this element \r\n    // Whenever a mutation (in this case just this component) occurs only \r\n    // this component will rerun as it is the only one that is subscribed to this channel\r\n    let mut radio = use_radio::\u003cData, DataChannel\u003e(DataChannel::SpecificListItemUpdate(list_n));\r\n\r\n    println!(\"Running DataChannel::SpecificListItemUpdate({list_n})\");\r\n\r\n    rsx!(\r\n        div {\r\n            button {\r\n                onclick: move |_| radio.write().lists[list_n].push(\"Hello World\".to_string()),\r\n                \"New Item\"\r\n            },\r\n            ul {\r\n                for (i, item) in radio.read().lists[list_n].iter().enumerate() {\r\n                    li {\r\n                        key: \"{i}\",\r\n                        \"{item}\"\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    )\r\n}\r\n```\r\n\r\n## Origins\r\n\r\nThe idea of `dioxus-radio` originally started when I was working in [`freya-editor`](https://github.com/marc2332/freya-editor). I struggled to optimize the state management as I was doing many unnecessary reruns, so I started working in a topic-subscription state management. Some time passed and eventually, I realized I could export this to a separate library. So I made `dioxus-radio` and it now actually powers `freya-editor` as well!\r\n\r\n## License\r\n\r\nMIT License\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdioxus-community%2Fdioxus-radio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdioxus-community%2Fdioxus-radio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdioxus-community%2Fdioxus-radio/lists"}