{"id":25289013,"url":"https://github.com/vivekmunde/react-pusu","last_synced_at":"2025-04-06T17:19:11.864Z","repository":{"id":42900334,"uuid":"252131268","full_name":"vivekmunde/react-pusu","owner":"vivekmunde","description":"Simple pub-sub implementation APIs for React Components","archived":false,"fork":false,"pushed_at":"2023-11-01T10:38:05.000Z","size":542,"stargazers_count":0,"open_issues_count":6,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-02T16:50:15.440Z","etag":null,"topics":["pub-sub","publish-subscribe","react","react-components-communication","react-state-management","reactjs"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/vivekmunde.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2020-04-01T09:33:44.000Z","updated_at":"2021-09-11T09:02:40.000Z","dependencies_parsed_at":"2024-12-04T20:33:41.497Z","dependency_job_id":"732e914c-5787-4733-93d6-7aa3f1a0e17d","html_url":"https://github.com/vivekmunde/react-pusu","commit_stats":{"total_commits":69,"total_committers":2,"mean_commits":34.5,"dds":"0.21739130434782605","last_synced_commit":"4bf68505bd84ee66ca6678e1dea071afd042dfd8"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vivekmunde%2Freact-pusu","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vivekmunde%2Freact-pusu/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vivekmunde%2Freact-pusu/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vivekmunde%2Freact-pusu/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vivekmunde","download_url":"https://codeload.github.com/vivekmunde/react-pusu/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247517946,"owners_count":20951721,"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":["pub-sub","publish-subscribe","react","react-components-communication","react-state-management","reactjs"],"created_at":"2025-02-12T23:27:47.733Z","updated_at":"2025-04-06T17:19:11.820Z","avatar_url":"https://github.com/vivekmunde.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react-pusu \n\nSimple `pub-sub` implementation APIs, HOCs \u0026 Hooks for [React](https://reactjs.org/) Components.\n\n\u003e **Pub-Sub** implementation is one of the effective ways and most useful when the components, which are rendered across the page, even under different component hierarchies, need to communicate with each other.\nA simple example can be, a data refresh button placed in the header of the application. On click of this button the page should reload the data from server. There can be multiple pages which may need this type of functionality. Also, there can be multiple sections on a page which need to reload the data using their own API calls (may be using redux). So all these pages \u0026 components can actually subscribe to the refresh publication event. The refresh button can, on click, publish the event. And then all the subscribers can reload the data (may be using redux) from server by calling their own apis.\n\n## Compatibility\n| React Version | react-pusu Compatibility |\n|--|--|\n| \u003e= React@16.8 | ^2.0.0 |\n| React@15, \u003c= React@16.7 | ^1.0.0 |\n\n## How to install\n\n`yarn add pusu react-pusu`\n\n`npm install --save pusu react-pusu`\n\n## createPublication\u0026lt;T\u0026gt;([name])\n**Parameters**:\n- `name`: *(Optional)* String - Publication name. Useful in debugging.\n\n**Return value**: Object - New publication\n\nCreates \u0026 returns a unique new publication object.\n\nPublication object is a simple javascript object `{ subscribers: [] }` which has an array named `subscribers`. The array `subscribers` actually holds the references to the subscriber functions. Result is, all the subscribers (i.e. functions) of the publication are mapped inside the publication object itself. Whenever a publiser publishes any data for a publication then all the subscribers inside the publication are called with this data.\n\nTypeScript\n\n```\n// refresh-page-data-publication.ts\n\nimport { createPublication } from 'pusu';\n\nexport default createPublication\u003c{ asOfDate: Date }\u003e('Refresh page data');\n```\n\nJavaScript\n\n```\n// refresh-page-data-publication.js\n\nimport { createPublication } from 'pusu';\n\nexport default createPublication('Refresh page Data');\n```\n\n### Unique publication every time\n\n**Creation of a publication makes sure that each publication is unique in itself and removes the need of maintaining a unique key for each publication.**\n\nEven if multiple publications created with same `name`, then each publication will be treated as a separate publication without any conflicts.\n\nBelow code creates two separate unique publications `publication1` \u0026 `publication2` even though the publication names are same. Name is just for the sake of naming the publication so that its useful during debugging any issues.\n\nTypeScript\n\n```\nimport { createPublication } from 'pusu';\n\nconst publication1 = createPublication\u003c{ asOfDate: Date }\u003e('Refresh page data');\nconst publication2 = createPublication\u003c{ asOfDate: Date }\u003e('Refresh page data');\n\nconsole.log(publication1 === publication2); //false\n```\n\nJavaScript\n\n```\nimport { createPublication } from 'pusu';\n\nconst publication1 = createPublication('Refresh page data');\nconst publication2 = createPublication('Refresh page data');\n\nconsole.log(publication1 === publication2); //false\n```\n\n## publish(publication, [data])\n**Parameters**:\n- `publication`: *(Required)* Object - Publication object created using the api `createPublication()`\n- `[data]`: *(Optional)* Any - The data is passed as is to the subscribers listening to the publication. Its a way of passing data to the subscribers.\n\n`publish` method calls all the subscribers subscribed to the `publication` (provided as a first argument). It calls the subscribers with the data.\n\n```\nimport { publish } from 'pusu';\nimport refreshPageDataPublication from './publications/refresh-page-data-publication';\n\nconst RefreshPageDataButton = ({ company }) =\u003e (\n  \u003cbutton\n    onClick={()=\u003e {\n      // Publish the data \n      publish(publication, {asOfDate: new Date() };\n    }}\n  \u003e\n    Refresh\n  \u003c/button\u003e\n);\n\nexport default RefreshPageDataButton;\n```\n\n## subscribe(publication, subscriber)\n**Parameters**:\n- `publication`: *(Required)* Object - Publication object created using the api `createPublication`\n- `subscriber`: *(Required)* Function - A subscriber function which will be called by the publisher. This function will receive the data published by the publisher.\n\n**Return value**: Function - A function when called then the `subscriber` is unsubscribed and no longer called by the publisher.\n\n\u003e Using HOC `withSubscribe` or hook `useSubscribe` removes the need of unsubscribe implementation, which is explained in the later sections.\n\n```\nimport { subscribe } from 'pusu';\nimport refreshPageDataPublication from './publications/refresh-page-data-publication';\n\nclass DashboardCompanySatistics extends React.Component {\n  constructor(props, context) {\n    super(props, context);\n\n    // Subscribe to the publication\n    this.unsubscribe = props.subscribe(refreshPageDataPublication, this.refreshData);\n  }\n\n  refreshData = ({ asOfDate }) =\u003e {\n    // load the data (may be using redux)\n  }\n\n  componentWillUnmount() {\n    // Unsubscribe from the publication\n    if(this.unsubscribe) {\n      this.unsubscribe();\n    }\n\n    // Note: \n    // Using HOC `withSubscribe` or hook `useSubscribe` removes the need of above unsubscribe implementation, which is explained in the later sections. \n  }\n  \n  render() {\n    return (\n      \u003csection\u003e\n        // render the statistics here ...\n      \u003c/section\u003e\n    );\n  }\n}\n\nexport default DashboardCompanySatistics;\n```\n\n## withSubscribe(Component)\n**Parameters**:\n- `Component`: *(Required)* - React Component\n\n`withSubscribe` supplies a function `subscribe` as a property to the React Component. The Component can subscribe to the publication and can receive the data using this function, whenver the publisher publishes it.\n\n**`withSubscribe` makes sure that all the subscriptions are removed/unsubscribed before the component is unmounted.** This way the consumer React Component can use the `props.subscribe`, even multiple times, without worrying about unsubscribing before it is unmounted.\n\n```\nimport { withSubscribe } from 'react-pusu';\nimport refreshPageDataPublication from './publications/refresh-page-data-publication';\n\nclass DashboardCompanySatistics extends React.Component {\n  constructor(props, context) {\n    super(props, context);\n    props.subscribe(refreshPageDataPublication, this.refreshData);\n  }\n\n  refreshData = ({ asOfDate }) =\u003e {\n    // load the data (may be using redux)\n  }\n  \n  render() {\n    return (\n      \u003csection\u003e\n        // render the statistics here ...\n      \u003c/section\u003e\n    );\n  }\n}\n\nexport default withSubscribe(DashboardCompanySatistics);\n```\n\n#### Unsubscribing explicitly \n`props.subscribe`, when called, returns a function which can be called to unsubscribe from the publication. Sometimes component may need to unsubscribe based on some condition or action, for those cases the function returned by `props.subscribe` can be called to unsubscribe.\n\n```\nimport { withSubscribe } from 'react-pusu';\nimport refreshPageDataPublication from './publications/refresh-page-data-publication';\n\nclass DashboardCompanySatistics extends React.Component {\n  constructor(props, context) {\n    super(props, context);\n\n    // Assign the unsubscriber function to the class member/variable\n    this.unsubscribeFromRefreshPublication = props.subscribe(refreshPageDataPublication, this.refreshData);\n  }\n\n  refreshData = ({ asOfDate }) =\u003e {\n    // load the data (may be using redux)\n  }\n\n  onSomeAction = () =\u003e {\n    // Unsubscribe from publication\n    this.unsubscribeFromRefreshPublication();\n  }\n  \n  render() {\n    return (\n      \u003csection\u003e\n        // render the statistics here ...\n      \u003c/section\u003e\n    );\n  }\n}\n\nexport default withSubscribe(DashboardCompanySatistics);\n```\n\n## useSubscribe()\n`useSubscribe` hook returns a function `subscribe`. The Component can subscribe to the publication and can receive the data using this `subscribe` function, whenver the publisher publishes it.\n\n**`useSubscribe` makes sure that all the subscriptions are removed/unsubscribed before the component is unmounted.** This way the consumer React Component can use the `subscribe`, even multiple times, without worrying about unsubscribing before it is unmounted.\n\n```\nimport { useSubscribe } from 'react-pusu';\nimport refreshPageDataPublication from './publications/refresh-page-data-publication';\n\nconst DashboardCompanySatistics = () =\u003e {\n  const subscribe = useSubscribe();\n  \n  useEffect(() =\u003e {\n    const refreshData = ({ asOfDate }) =\u003e {\n      // load the data (may be using redux)\n    }\n\n    subscribe(refreshPageDataPublication, refreshData);\n  }\n   \n  return (\n    \u003csection\u003e\n      // render the statistics here ...\n    \u003c/section\u003e\n  );\n};\n\nexport default DashboardCompanySatistics;\n```\n\n#### Unsubscribing explicitely \n`subscribe`, when called, returns a function which can be called to unsubscribe from the publication. Sometimes component may need to unsubscribe based on some condition or action, for those cases the function returned by `subscribe` can be called to unsubscribe.\n\n```\nimport { useSubscribe } from 'react-pusu';\nimport refreshPageDataPublication from './publications/refresh-page-data-publication';\n\nconst DashboardCompanySatistics = () =\u003e {\n  const ref = useRef({ unsubscribeFromRefreshPublication: () =\u003e {} });\n  const subscribe = useSubscribe();\n  \n  useEffect(() =\u003e {\n    const refreshData = ({ asOfDate }) =\u003e {\n      // load the data (may be using redux)\n    }\n\n    ref.current.unsubscribeFromRefreshPublication = subscribe(refreshPageDataPublication, refreshData);\n  }\n  \n  const onSomeAction = () =\u003e {\n    // Unsubscribe from publication\n    ref.current.unsubscribeFromRefreshPublication();\n  }\n   \n  return (\n    \u003csection\u003e\n      // render the statistics here ...\n    \u003c/section\u003e\n  );\n};\n\nexport default DashboardCompanySatistics;\n```\n\n## Migrating from 2.0 to 2.1\n\n\n### Breaking change\n\n- The version 2.1 will need `pusu` as a separate dependency to be installed\n- The version 2.1 will allow only one parameter while publishing the data \u0026 subscribing to the data.\n\n\n### 2.0\n\nThe version 2.0 were allowing more than one parameters while publishing the data.\n\nIn the example below, publisher is publishing date and company id as two different parameters.\n\n```\nimport { publish } from 'pusu';\nimport refreshPageDataPublication from './publications/refresh-page-data-publication';\n\nconst RefreshPageDataButton = ({ company }) =\u003e (\n  \u003cbutton\n    onClick={()=\u003e {\n      // Publish the data \n      publish(publication, new Date(), company._id);\n    }}\n  \u003e\n    Refresh\n  \u003c/button\u003e\n);\n\nexport default RefreshPageDataButton;\n```\n\nThe subscriber receives two arguments as date and company id.\n \n```\nimport { useSubscribe } from 'react-pusu';\nimport refreshPageDataPublication from './publications/refresh-page-data-publication';\n\nconst DashboardCompanySatistics = () =\u003e {\n  const subscribe = useSubscribe();\n  \n  useEffect(() =\u003e {\n    const refreshData = (asOf, companyId) =\u003e {\n      // load the data (may be using redux)\n    }\n\n    subscribe(refreshPageDataPublication, refreshData);\n  }\n   \n  return (\n    \u003csection\u003e\n      // render the statistics here ...\n    \u003c/section\u003e\n  );\n};\n\nexport default DashboardCompanySatistics;\n```\n\n### 2.1\n\nThe version 2.1 will allow only one parameter while publishing the data \u0026 subscribing to the data.\n\nIn the example below, publisher is publishing one JSON object consisting of date and company id.\n\n```\nimport { publish } from 'pusu';\nimport refreshPageDataPublication from './publications/refresh-page-data-publication';\n\nconst RefreshPageDataButton = ({ company }) =\u003e (\n  \u003cbutton\n    onClick={()=\u003e {\n      // Publish the data \n      publish(publication, { asOfDate: new Date(), companyId: company._id });\n    }}\n  \u003e\n    Refresh\n  \u003c/button\u003e\n);\n\nexport default RefreshPageDataButton;\n```\n\nThe subscriber receives it as the same JSON object consisting of date and company id.\n\n```\nimport { withSubscribe } from 'react-pusu';\nimport refreshPageDataPublication from './publications/refresh-page-data-publication';\n\nclass DashboardCompanySatistics extends React.Component {\n  constructor(props, context) {\n    super(props, context);\n    props.subscribe(refreshPageDataPublication, this.refreshData);\n  }\n\n  refreshData = ({ asOfDate, companyId }) =\u003e {\n    // load the data (may be using redux)\n  }\n  \n  render() {\n    return (\n      \u003csection\u003e\n        // render the statistics here ...\n      \u003c/section\u003e\n    );\n  }\n}\n\nexport default withSubscribe(DashboardCompanySatistics);\n```\n\n```\nimport { useSubscribe } from 'react-pusu';\nimport refreshPageDataPublication from './publications/refresh-page-data-publication';\n\nconst DashboardCompanySatistics = () =\u003e {\n  const subscribe = useSubscribe();\n  \n  useEffect(() =\u003e {\n    const refreshData = ({ asOfDate, companyId }) =\u003e {\n      // load the data (may be using redux)\n    }\n\n    subscribe(refreshPageDataPublication, refreshData);\n  }\n   \n  return (\n    \u003csection\u003e\n      // render the statistics here ...\n    \u003c/section\u003e\n  );\n};\n\nexport default DashboardCompanySatistics;\n```\n\n\n## Migrating from 1.1 to 1.2\n\n\n### Breaking change\n\n- The version 1.2 will need `pusu` as a separate dependency to be installed\n- The version 1.2 will allow only one parameter while publishing the data \u0026 subscribing to the data.\n\n\n### 1.1\n\nThe version 1.1 wes allowing more than one parameters while publishing the data.\n\nIn the example below, publisher is publishing date and company id as two different parameters.\n\n```\nimport { publish } from 'pusu';\nimport refreshPageDataPublication from './publications/refresh-page-data-publication';\n\nconst RefreshPageDataButton = ({ company }) =\u003e (\n  \u003cbutton\n    onClick={()=\u003e {\n      // Publish the data \n      publish(publication, new Date(), company._id);\n    }}\n  \u003e\n    Refresh\n  \u003c/button\u003e\n);\n\nexport default RefreshPageDataButton;\n```\n\nThe subscriber receives two arguments as date and company id.\n \n```\nimport { useSubscribe } from 'react-pusu';\nimport refreshPageDataPublication from './publications/refresh-page-data-publication';\n\nconst DashboardCompanySatistics = () =\u003e {\n  const subscribe = useSubscribe();\n  \n  useEffect(() =\u003e {\n    const refreshData = (asOf, companyId) =\u003e {\n      // load the data (may be using redux)\n    }\n\n    subscribe(refreshPageDataPublication, refreshData);\n  }\n   \n  return (\n    \u003csection\u003e\n      // render the statistics here ...\n    \u003c/section\u003e\n  );\n};\n\nexport default DashboardCompanySatistics;\n```\n\n### 1.2\n\nThe version 1.2 will allow only one parameter while publishing the data \u0026 subscribing to the data.\n\nIn the example below, publisher is publishing one JSON object consisting of date and company id.\n\n```\nimport { publish } from 'pusu';\nimport refreshPageDataPublication from './publications/refresh-page-data-publication';\n\nconst RefreshPageDataButton = ({ company }) =\u003e (\n  \u003cbutton\n    onClick={()=\u003e {\n      // Publish the data \n      publish(publication, { asOfDate: new Date(), companyId: company._id });\n    }}\n  \u003e\n    Refresh\n  \u003c/button\u003e\n);\n\nexport default RefreshPageDataButton;\n```\n\nThe subscriber receives it as the same JSON object consisting of date and company id.\n\n```\nimport { withSubscribe } from 'react-pusu';\nimport refreshPageDataPublication from './publications/refresh-page-data-publication';\n\nclass DashboardCompanySatistics extends React.Component {\n  constructor(props, context) {\n    super(props, context);\n    props.subscribe(refreshPageDataPublication, this.refreshData);\n  }\n\n  refreshData = ({ asOfDate, companyId }) =\u003e {\n    // load the data (may be using redux)\n  }\n  \n  render() {\n    return (\n      \u003csection\u003e\n        // render the statistics here ...\n      \u003c/section\u003e\n    );\n  }\n}\n\nexport default withSubscribe(DashboardCompanySatistics);\n```\n\n```\nimport { useSubscribe } from 'react-pusu';\nimport refreshPageDataPublication from './publications/refresh-page-data-publication';\n\nconst DashboardCompanySatistics = () =\u003e {\n  const subscribe = useSubscribe();\n  \n  useEffect(() =\u003e {\n    const refreshData = ({ asOfDate, companyId }) =\u003e {\n      // load the data (may be using redux)\n    }\n\n    subscribe(refreshPageDataPublication, refreshData);\n  }\n   \n  return (\n    \u003csection\u003e\n      // render the statistics here ...\n    \u003c/section\u003e\n  );\n};\n\nexport default DashboardCompanySatistics;\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvivekmunde%2Freact-pusu","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvivekmunde%2Freact-pusu","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvivekmunde%2Freact-pusu/lists"}