Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Phoenix LiveReact

Phoenix LiveReact

さっちゃん

June 30, 2019
Tweet

More Decks by さっちゃん

Other Decks in Programming

Transcript

  1. Phoenix LiveView: Interactive, Real-Time Apps. No Need to Write JavaScript.

    https://dockyard.com/blog/2018/12/12/phoenix-liveview- interactive-real-time-apps-no-need-to-write-javascript
  2. Write Elixir. defmodule ExampleWeb.CounterLive do use Phoenix.LiveView def render(assigns) do

    ~L""" Count: <%= @count %> """ end def mount(%{}, socket) do if connected?(socket), do: :timer.send_interval(1000, self(), :count_up) {:ok, assign(socket, :count, 0)} end def handle_info(:count_up, socket) do count = socket.assigns.count {:noreply, assign(socket, :count, count + 1)} end end
  3. Taking the principle of excluded middle from the mathematician would

    be the same, say, as proscribing the telescope to the astronomer or to the boxer the use of his fists. Hilbert (1927)
  4. Taking the JavaScript from the Web UI would be the

    same, say, as proscribing the principle of excluded middle from the mathematician.
  5. Improving UX with Phoenix Channels & React Hooks – Flatiron

    Labs – Medium https://medium.com/flatiron-labs/improving-ux-with- phoenix-channels-react-hooks-8e661d3a771e
  6. defmodule ExampleWeb.RoomChannel do use ExampleWeb, :channel def join("room:lobby", payload, socket)

    do socket = assign(socket, :count, 0) :timer.send_interval(1000, self(), :count_up) {:ok, socket} end def handle_info(:count_up, socket) do count = socket.assigns.count + 1 socket = assign(socket, :count, count) push(socket, "count_up", %{count: count}) {:noreply, socket} end end
  7. import React from "react"; import ReactDOM from "react-dom"; export default

    function main() { ReactDOM.render( <SocketProvider wsUrl={"/socket"} options={{ token: window.userToken }}> <App /> </SocketProvider>, document.getElementById("app") ); }
  8. import { Socket } from "phoenix"; import { createContext, useEffect

    } from "react"; const SocketContext = createContext(); function SocketProvider({ wsUrl, options, children }) { const socket = new Socket(wsUrl, { params: options }); useEffect(() => { socket.connect(); }, [options, wsUrl]); return ( <SocketContext.Provider value={socket}>{children}</SocketContext.Provider> ); } SocketProvider.defaultProps = { options: {} };
  9. import { useContext, useEffect, useReducer } from "react"; function useChannel(channelTopic,

    reducer, initialState) { const socket = useContext(SocketContext); const [state, dispatch] = useReducer(reducer, initialState); useEffect(() => { const channel = socket.channel(channelTopic, {}); channel.onMessage = (event, payload) => { dispatch({ event, payload }); return payload; }; channel.join(); return () => { channel.leave(); }; }, [channelTopic]); return state; }
  10. function appReducer(state, { event, payload }) { switch (event) {

    case "count_up": return { ...state, count: payload.count }; default: return state; } } function App(props) { const initialState = { count: 0 }; const { count } = useChannel("room:lobby", appReducer, initialState); return <div>Count: {count}</div>; } Done!