dwyl / phoenix-chat-example

💬 The Step-by-Step Beginners Tutorial for Building, Testing & Deploying a Chat app in Phoenix 1.7 [Latest] 🚀

Home Page:https://phoenix-chat.fly.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unable to join Object { reason: "unmatched topic" }

tomasgtz opened this issue · comments

Hello,
I followed whole tutorial, however I am not able to make it run well.

I am getting this error at chrome, console Unable to join Object { reason: "unmatched topic" }

also in the erlang console I get this error
[warn] Ignoring unmatched topic "topic:subtopic" in ChatWeb.UserSocket

I checked the room name in
lib/chat_web/channels/room_channel.ex
lib/chat_web/channels/user_socket.ex
assets/js/app.js

to ensure all three files have the same room:main (in my case)

Can you help me please?

Hi @tomasgtz, thanks for opening this issue.
Is your code on GitHub? If you can share a link to it i/we can help debug. 👍

Hi @nelsonic
I don't have it in a git, however here are the contents of the three files that I changed from this github.
I didn't changed anything else

room_channel.ex
defmodule ChatWeb.RoomChannel do
use ChatWeb, :channel

def join("room:lobby", payload, socket) do
if authorized?(payload) do
{:ok, socket}
else
{:error, %{reason: "unauthorized"}}
end
end

# Channels can be used in a request/response fashion
# by sending replies to requests from the client
def handle_in("ping", payload, socket) do
{:reply, {:ok, payload}, socket}
end

# It is also common to receive messages from the client and
# broadcast to everyone in the current topic (room:lobby).
def handle_in("shout", payload, socket) do
broadcast socket, "shout", payload
{:noreply, socket}
end

# Add authorization logic here as required.
defp authorized?(_payload) do
true
end
end

user_socket.ex
`defmodule ChatWeb.UserSocket do
use Phoenix.Socket

# # Channels
channel "room:lobby", ChatWeb.ChatRoomChannel

# # Transports
# transport :websocket, Phoenix.Transports.WebSocket
# transport :longpoll, Phoenix.Transports.LongPoll

# Socket params are passed from the client and can
# be used to verify and authenticate a user. After
# verification, you can put default assigns into
# the socket that will be set for all channels, ie
#
# {:ok, assign(socket, :user_id, verified_user_id)}
#
# To deny connection, return :error.
#
# See Phoenix.Token documentation for examples in
# performing token verification on connect.
def connect(_params, socket) do
{:ok, socket}
end

# Socket id's are topics that allow you to identify all sockets for a given user:
#
# def id(socket), do: "user_socket:#{socket.assigns.user_id}"
#
# Would allow you to broadcast a "disconnect" event and terminate
# all active sockets and channels for a given user:
#
# ChatWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{})
#
# Returning nil makes this socket anonymous.
def id(_socket), do: nil
end`

assets/js/app.js
`// We need to import the CSS so that webpack will load it.
// The MiniCssExtractPlugin is used to separate it out into
// its own CSS file.
import css from "../css/app.css"

// webpack automatically bundles all modules in your
// entry points. Those entry points can be configured
// in "webpack.config.js".
//
// Import dependencies
//
import "phoenix_html"

// Import local files
//
// Local files can be imported directly using relative paths, for example:
import socket from "./socket"

var channel = socket.channel('room:lobby', {}); // connect to chat "room"

channel.on('shout', function (payload) { // listen to the 'shout' event
var li = document.createElement("li"); // creaet new list item DOM element
var name = payload.name || 'guest'; // get name from payload or set default
li.innerHTML = '' + name + ': ' + payload.message;
ul.appendChild(li); // append to list
});

channel.join(); // join the channel.

var ul = document.getElementById('msg-list'); // list of messages.
var name = document.getElementById('name'); // name of message sender
var msg = document.getElementById('msg'); // message input field

// "listen" for the [Enter] keypress event to send a message:
msg.addEventListener('keypress', function (event) {
if (event.keyCode == 13 && msg.value.length > 0) { // don't sent empty msg.
channel.push('shout', { // send the message to the server
name: name.value, // get value of "name" of person sending the message
message: msg.value // get message text (value) from msg input field.
});
msg.value = ''; // reset the message input field for next message.
}
});`

Also here is what console is displaying

[warn] Ignoring unmatched topic "topic:subtopic" in ChatWeb.UserSocket
[error] {:EXIT, {:undef, [{ChatWeb.ChatRoomChannel, :start_link, [{%{}, {#PID<0.413.0>, #Reference<0.3880366180.3763601409.213203>}, %Phoenix.Socket{assigns: %{}, channel: ChatWeb.ChatRoomChannel, channel_pid: nil, endpoint: ChatWeb.Endpoint, handler: ChatWeb.UserSocket, id: nil, join_ref: "1137", joined: false, private: %{}, pubsub_server: Chat.PubSub, ref: nil, serializer: Phoenix.Socket.V2.JSONSerializer, topic: "room:lobby", transport: :websocket, transport_pid: #PID<0.413.0>}}], []}, {:supervisor, :do_start_child_i, 3, [file: 'supervisor.erl', line: 379]}, {:supervisor, :handle_call, 3, [file: 'supervisor.erl', line: 404]}, {:gen_server, :try_handle_call, 4, [file: 'gen_server.erl', line: 661]}, {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 690]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]}]}}

just comment lines in assets/js/socket.js

let channel = socket.channel("topic:subtopic", {})
channel.join()
  .receive("ok", resp => { console.log("Joined successfully", resp) })
  .receive("error", resp => { console.log("Unable to join", resp) })

Did you try this?

let channel = socket.channel("room:lobby", {})
channel.join()
  .receive("ok", resp => { console.log("Joined successfully", resp) })
  .receive("error", resp => { console.log("Unable to join", resp) })

I've added this to to the README.md in #33