Getting repeated payloads on Channel.on in Phoenix websockets

I am learning phoenix channels and these are my simple server and client codes

def handle_in("pomodoro1", _payload, socket) do
    push(socket, "status", %{status: "start"})

    :timer.sleep(5000)
    push(socket, "status", %{status: "finish"})
    {:reply, :ok, socket}
  end
const startPomodoro = () => {
  channel.push("pomodoro1")
    .receive("ok", resp => console.log("received OK", resp))
    .receive("error", resp => console.log("received error", resp))
    .receive("timeout", resp => console.log("timeout", resp))
  
  channel.on("status", resp => console.log(resp))
}

I getting somewhat strange response. On 1st invocation of client function I get expected response from the server

[Sun Nov 08 2020 16:22:50.923]  LOG      {"status": "start"}
[Sun Nov 08 2020 16:22:55.921]  LOG      {"status": "finish"}
[Sun Nov 08 2020 16:22:55.922]  LOG      received OK {}

but on 2nd invocation, I get twice the response I expect

[Sun Nov 08 2020 16:23:03.643]  LOG      {"status": "start"}
[Sun Nov 08 2020 16:23:03.644]  LOG      {"status": "start"}
[Sun Nov 08 2020 16:23:08.634]  LOG      {"status": "finish"}
[Sun Nov 08 2020 16:23:08.635]  LOG      {"status": "finish"}
[Sun Nov 08 2020 16:23:08.635]  LOG      received OK {}

…and so on thrice the response on 3rd invocation. Any advice?

I haven’t used Phoenix channels but sounds like you are subscribing to channel twice.

By subscribing channel do you mean joining channel twice ? I am not joining channel twice going by logs of phoenix server. I had added code to prevent joining channel twice after hot reloading

const App = () => {
  const [channelStatus, setChannelStatus] = useState('')

  useEffect(() => {
    if(channelStatus !== "Channel Joined") {
      channel.join()
        .receive('ok', () => setChannelStatus("Channel Joined"))
        .receive('error', () => setChannelStatus("Failed to join"))
    }
  }, [])
.
.
.

My React skills are bit rusty but is it possible that code is called twice? Because there is possible of race condition there. channelStatus is checked for “Channel Joined” but receive has an asyncronous callback. So it is possible for multiple calls to go channel.join until you set channelStatus when you receive response from server.