{"id":18000114,"url":"https://github.com/tylersamples/phoenix-hooks","last_synced_at":"2025-07-10T22:04:03.338Z","repository":{"id":57323002,"uuid":"366879325","full_name":"tylersamples/phoenix-hooks","owner":"tylersamples","description":"Phoenix React Hooks","archived":false,"fork":false,"pushed_at":"2021-05-24T03:00:33.000Z","size":145,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-26T16:05:53.682Z","etag":null,"topics":["elixir","phoenix-channels","phoenix-framework","react","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":false,"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/tylersamples.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}},"created_at":"2021-05-12T23:28:30.000Z","updated_at":"2024-05-28T07:34:46.000Z","dependencies_parsed_at":"2022-09-13T19:00:29.908Z","dependency_job_id":null,"html_url":"https://github.com/tylersamples/phoenix-hooks","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/tylersamples/phoenix-hooks","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylersamples%2Fphoenix-hooks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylersamples%2Fphoenix-hooks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylersamples%2Fphoenix-hooks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylersamples%2Fphoenix-hooks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tylersamples","download_url":"https://codeload.github.com/tylersamples/phoenix-hooks/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylersamples%2Fphoenix-hooks/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264673135,"owners_count":23647547,"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":["elixir","phoenix-channels","phoenix-framework","react","typescript"],"created_at":"2024-10-29T23:09:40.899Z","updated_at":"2025-07-10T22:04:03.270Z","avatar_url":"https://github.com/tylersamples.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Phoenix Hooks\n\nPhoenix Sockets, Channels, and Presence with React hooks.\n\n## Getting Started\n\nInstallation:\n```bash\n$ npm install phoenix-hooks\n```\n\n### Phoenix Socket\n\n```typescript\nimport { useSocket } from 'phoenix-hooks'\n\nconst { socket, socketState } = useSocket(`//localhost:4000/socket`, {params: {userToken: \"\u003ctoken value\u003e\"}})\n```\n\n#### `useSocket`\n\n#### Arguments\n* `url`: `string`\n  * `wss://localhost:4000/socket`\n  * `ws://localhost:4000/socket`\n  * `localhost:4000/socket`\n  * `/socket`\n* `opts`: `SocketOptions`\n\n```typescript\ntype SocketOptions = {\n  binaryType: BinaryType;\n  params: object | (() =\u003e object);\n  transport: string;\n  timeout: number;\n  heartbeatIntervalMs: number;\n  longpollerTimeout: number;\n  encode: (payload: object, callback: (encoded: any) =\u003e void) =\u003e void;\n  decode: (payload: string, callback: (decoded: any) =\u003e void) =\u003e void;\n  logger: (kind: string, message: string, data: any) =\u003e void;\n  reconnectAfterMs: (tries: number) =\u003e number;\n  rejoinAfterMs: (tries: number) =\u003e number;\n  vsn: string;\n  onOpen: () =\u003e void;\n  onClose: () =\u003e void;\n  onError: (any) =\u003e void;\n}\n```\n\n#### `socketState`\n```typescript\nenum SocketStates {\n  UNINSTANTIATED = -1,\n  CONNECTING,\n  OPEN,\n  CLOSING,\n  CLOSED,\n}\n```\nEnum representing the socket state. \n\n#### `socket`\nThe underlying Phoenix Socket class. \n\n#### `socketDisconnect`\nDisconnect to the socket.\n\n##### Example\n```typescript jsx\n\u003cbutton onClick={() =\u003e socketDisconnect()}\u003eDisconnect\u003c/button\u003e\n```\n\n#### `socketConnect`\nConnect to the socket. `useSocket` will start the socket for you so this may not be needed; use for explicitly reconnecting after using `socketDisconnect`.\n\n##### Example\n```typescript jsx\n\u003cbutton onClick={() =\u003e socketConnect()}\u003eConnect\u003c/button\u003e\n```\n\n#### `socketHandleMessage`\nHandle callback on each message received \n\n##### Example\n```typescript jsx\nuseEffect(() =\u003e {\n  socketHandleMessage(message =\u003e {\n    console.log('socketHandleMessage', message)\n  })\n}, [socketHandleMessage])\n```\n\n### Phoenix Channels\n\n```typescript\nimport { useChannels } from 'phoenix-hooks'\n\nconst { socket } = useSocket(`//localhost:4000/socket`) // Optional, see Provider\nconst { handleChannelEvent, pushChannelEvent } = \n  useChannels(`chat:${123}`, {onJoin: params =\u003e {\n    // Use params set join/3 response\n  }})\n```\n\n#### `useChannels`\nConnect to a given Phoenix channel.\n\n#### Arguments\n* `channelName`: `string`\n* `opts`: `ChannelOptions`\n\n```typescript\ntype ChannelOptions = {\n  onClose?: () =\u003e void; \n  onError?: (err: any) =\u003e void;\n  onLeave?: () =\u003e void;\n  onJoin?: (object) =\u003e void; // Useful for getting join/3 response \n  onTimeout?: () =\u003e void;\n  socket: Socket;\n  params: object;\n}\n```\n\n\n#### `channelState`\n```typescript\nenum ChannelStates {\n  CLOSED,\n  ERRORED,\n  JOINED,\n  JOINING,\n  LEAVING\n}\n```\nEnum representing the connection status to a channel. `JOINED` is the \"everything is fine here\" state.\n\n#### `channel`\nThe underlying Phoenix Channel class.\n\n#### `handleChannelEvent`\n\nHandle callback for a specific channel event\n\n##### Example\n```typescript jsx\nuseEffect(() =\u003e {\n  handleChannelEvent(\"selection\", response =\u003e {\n    console.log('handleChannelEvent', response)\n  })\n}, [socketHandleMessage])\n```\n\n#### `pushChannelEvent`\n\nPush an event with a payload. Phoenix handles via `handle_in/3`\n\n#### `leaveChannel`\n\nLeave the channel\n\n### Phoenix Presence\n\n```typescript\nimport { useSocket, useChannels, usePresence } from 'phoenix-hooks'\n\nconst { socket } = useSocket(`//localhost:4000/socket`) // Optional, see Provider\nconst { channel } = useChannels(`chat:${123}`, {socket: socket})\nconst { handlePresenceSync } = usePresence(channel)\n```\n\n#### `usePresence`\nUse Phoenix Presence for a given channel.\n\n#### Arguments\n* `channel`: `Channel` Channel from a previous `useChannels` call\n\n#### `presence`\nThe underlying Phoenix Presence class.\n\n#### `handlePresenceSync`\n\nHandle callback on sync.\n\n##### Example\n```typescript\nconst [editors, setEditors] = useState([])\n\nuseEffect(() =\u003e {\n  handlePresenceSync(users =\u003e {\n    setEditors(users.sort((u1, u2) =\u003e {\n      return u1.metas[0].online_at \u003e u2.metas[0].online_at\n    }))\n  })\n}, [handlePresenceSync])\n```\n\n#### `handlePresenceJoin`\n\nHandle callback upon `presence_diff` join\n\n#### `handlePresenceLeave`\n\nHandle callback upon `presence_diff` leave\n\n### Provider\n\n```typescript jsx\nimport { PhoenixSocketProvider } from 'phoenix-hooks'\n\nfunction App() {\n  return (\n    \u003cPhoenixSocketProvider url={`//localhost:4000/socket`}\u003e\n      {/* Your component */}\n    \u003c/PhoenixSocketProvider\u003e\n  )\n}\n```\n\n#### Attributes\n* `url`: `string`\n  * `wss://localhost:4000/socket`\n  * `ws://localhost:4000/socket`\n  * `localhost:4000/socket`\n  * `/socket`\n* `opts`: `SocketOptions`\n\n```typescript\ntype SocketOptions = {\n  binaryType: BinaryType;\n  params: object | (() =\u003e object);\n  transport: string;\n  timeout: number;\n  heartbeatIntervalMs: number;\n  longpollerTimeout: number;\n  encode: (payload: object, callback: (encoded: any) =\u003e void) =\u003e void;\n  decode: (payload: string, callback: (decoded: any) =\u003e void) =\u003e void;\n  logger: (kind: string, message: string, data: any) =\u003e void;\n  reconnectAfterMs: (tries: number) =\u003e number;\n  rejoinAfterMs: (tries: number) =\u003e number;\n  vsn: string;\n  onOpen: () =\u003e void;\n  onClose: () =\u003e void;\n  onError: (any) =\u003e void;\n}\n```\n## License\n\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftylersamples%2Fphoenix-hooks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftylersamples%2Fphoenix-hooks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftylersamples%2Fphoenix-hooks/lists"}