LiveReact 2.0 sends prop changes as patches instead of resending the whole payload on every update. Making that safe required one breaking change: structs passed as props must now say which of their fields may be sent to the browser.
1. Bump the dependency
def deps do
[
{:live_react, "~> 2.0"}
]
endThe JavaScript ships inside the Hex package, so refresh it too:
mix deps.get
npm install --prefix assets
2. Derive LiveReact.Encoder for struct props
Props used to be encoded with Jason.Encoder. They are now encoded with
LiveReact.Encoder, which converts structs to maps so they can be diffed
field by field.
If you pass a struct as a prop and it has no implementation, rendering raises a
Protocol.UndefinedError naming the struct. The fix is a @derive:
defmodule User do
@derive LiveReact.Encoder
defstruct [:id, :name, :email]
endEvery field except :__struct__ is encoded by default. Restrict that with
:only or :except — worth doing for anything holding secrets:
defmodule User do
@derive {LiveReact.Encoder, except: [:password_hash, :session_token]}
defstruct [:id, :name, :email, :password_hash, :session_token]
endFor a struct you do not own, derive it from outside the module:
# lib/my_app/encoders.ex
Protocol.derive(LiveReact.Encoder, SomeLibrary.Struct, only: [:id, :label])Or implement the protocol yourself when the shape needs work:
defimpl LiveReact.Encoder, for: Money do
def encode(money, opts) do
LiveReact.Encoder.encode(%{amount: money.amount, currency: money.currency}, opts)
end
endPlain maps, lists, strings, numbers and atoms are unaffected — nothing to do.
Neither are the structs LiveReact already implements: Date, Time,
NaiveDateTime, DateTime, Phoenix.HTML.Form,
Phoenix.LiveView.AsyncResult, Phoenix.LiveView.UploadConfig and
Phoenix.LiveView.UploadEntry. See
Props diffing and streams for the
shapes they produce.
Why not Jason.Encoder?
Jason.Encoder produces a JSON string. Diffing needs the intermediate map so
it can compare field by field, which is what LiveReact.Encoder returns. The
explicit-implementation requirement is deliberate: it keeps a struct from
silently shipping fields nobody intended to expose.
3. Check components that update frequently
Diffing is on by default and needs no code changes. If a component misbehaves after the upgrade, turn diffing off for it and compare:
<.react name="Chart" data={@points} diff={false} />That restores 1.x behavior for that component. Globally:
config :live_react, enable_props_diff: falseIf you find a case where diffing is wrong, please
open an issue — the goal is for
diff={false} to be a workaround rather than a fixture.
What else is new
Stream assigns can be passed straight to a component, without serializing them yourself:
<.react name="Messages" messages={@streams.messages} />