ericlathrop

ericlathrop

Phoenix-js-react-hooks - React Hooks for working with Phoenix Channels in JavaScript

I built a silly site for Halloween that uses Phoenix Channels on the backend, and React on the frontend. I had many problems integrating the official phoenix NPM module with my React components. After many iterations I’ve got something that fits in naturally with React function components, so I’ve extracted it as a library to share, and published it on NPM and GitLab.

Here’s part of the README:

phoenix-js-react-hooks

React hooks for working with Phoenix’s channels.

Usage

Wrap the top of your app with a <SocketProvider> so child components will have
access to the socket.

import { SocketProvider } from '@ericlathrop/phoenix-js-react-hooks';

function App() {
  const socketUrl = "wss://localhost:4000/socket";
  const socketOptions = { params: { 'user_id': userId }};

  return (
    <SocketProvider url={socketUrl} options={socketOptions}>
      <Main />
    </SocketProvider>
  );
}

The useChannel hook lets you subscribe to a channel, and the useEventHandler
hook lets you respond to incoming messages:

import React, { useContext, useEffect, useRef, useState } from 'react';
import { sendMessage, useChannel, useEventHandler } from '@ericlathrop/phoenix-js-react-hooks';

export function Main() {
  const [messages, setMessages] = useState([]);

  const room = 'cute kitties';
  const { channel: chatChannel } = useChannel('chat:' + room, undefined, (channel, { messages: initialMessages}) => {
    setMessages(initialMessages);
  });

  useEventHandler(chatChannel, 'new_message', message => {
    setMessages(messages.slice(0).concat([message]));
  });

  return (
    <div className="chat-messages" >
      {messages.map(({ id, message }) => <ChatMessage key={id} message={message} />)}
    </div>
  );
}

Most Liked

ericlathrop

ericlathrop

Correct. I was passing in a lambda so the handler would be different every time the component renders, so the reference needs to get updated.

For example:

  useEventHandler(chatChannel, 'new_message', message => {
    setMessages(messages.slice(0).concat([message]));
    messageWindow.current.scrollTop = messageWindow.current.scrollHeight;
  });

If the reference handler reference never got updated, then the first handler would stay with messages being [] and only the last message would get added for each event.

Where Next?

Popular in Libraries Top

wmnnd
Hi there, for my project DBLSQD, I needed a file storage solution that is a bit more flexible than Arc. Because I thought others might f...
New
arkgil
Hi all! I’m happy to announce that Telemetry v0.3.0 is out! This release marks the conversion from Elixir to Erlang so that all the libr...
New
kip
Image is an image processing library for Elixir. It is based upon the fabulous vix library that provides a libvips wrapper for Elixir. I...
574 16576 179
New
asiniy
Hey there! I wrote a download elixir package which does exactly what its name about - an easy way to download files. I saw solutions ...
New
nikokozak
Hello all, I’ve been working on Svonix - a library for quickly integrating Svelte components into Phoenix views. It’s a much-needed succ...
New
josevalim
EDIT: since Ecto 3.0 final version is out, this post was amended to use the final versions in the instructions below. Hi everyone, We a...
New
tmbb
I’ve published the first version of my Makeup library. It’s a syntax highlighter for Elixir in the spirit of Pygments, Currently it highl...
New
mbuhot
EctoJob A transactional job queue built with Ecto, PostgreSQL and GenStage Available on Hex.pm: ecto_job | Hex Docs: API Reference — ec...
New
mischov
import Meeseeks.CSS html = HTTPoison.get!("https://news.ycombinator.com/").body for story &lt;- Meeseeks.all(html, css("tr.athing")) do...
New
ostinelli
Let’s write a database! Well not really, but I think it’s a little sad that there doesn’t seem to be a simple in-memory distributed KV da...
New

Other popular topics Top

Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New

Sub Categories:

We're in Beta

About us Mission Statement