defmodule LiveReact do @moduledoc """ See READ.md for installation instructions and examples. """ use Phoenix.Component import Phoenix.HTML alias Phoenix.LiveView alias LiveReact.SSR require Logger @ssr_default Application.compile_env(:live_react, :ssr, true) @doc """ Render a React component. """ def react(assigns) do init = assigns.__changed__ == nil dead = assigns[:socket] == nil or not LiveView.connected?(assigns[:socket]) render_ssr? = init and dead and Map.get(assigns, :ssr, @ssr_default) # we manually compute __changed__ for the computed props and slots so it's not sent without reason {props, props_changed?} = extract(assigns, :props) component_name = Map.get(assigns, :name) assigns = assigns |> Map.put_new(:class, nil) |> Map.put(:__component_name, component_name) |> Map.put(:props, props) |> Map.put(:ssr_render, if(render_ssr?, do: ssr_render(component_name, props), else: nil)) computed_changed = %{ props: props_changed?, ssr_render: render_ssr? } assigns = update_in(assigns.__changed__, fn nil -> nil changed -> for {k, true} <- computed_changed, into: changed, do: {k, true} end) # It's important to not add extra `\n` in the inner div or it will break hydration ~H"""