Skip to content

Commit

Permalink
change-track non existing keys in maps (#3584)
Browse files Browse the repository at this point in the history
This prevents `@mymap[:foo]` from re-rendering when the map does not
contain the key `:foo`, is changed, and then still does not contain `:foo`.
  • Loading branch information
SteffenDE authored Dec 26, 2024
1 parent e2ec312 commit b9c8977
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/phoenix_live_view/engine.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,7 @@ defmodule Phoenix.LiveView.Engine do
defp recur_changed_assign([], head, assigns, changed) do
case {assigns, changed} do
{%{^head => value}, %{^head => value}} -> false
{m1, m2} when not is_map_key(m1, head) and not is_map_key(m2, head) -> false
{_, %{^head => value}} when is_map(value) -> value
{_, _} -> true
end
Expand Down
18 changes: 18 additions & 0 deletions test/phoenix_live_view/engine_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ defmodule Phoenix.LiveView.EngineTest do
assert changed(template, %{foo: 123}, nil) == ["123"]
assert changed(template, %{foo: 123}, %{}) == [nil]
assert changed(template, %{foo: 123}, %{foo: true}) == ["123"]
assert changed(template, %{}, %{}) == [nil]
assert changed(template, %{}, %{foo: true}) == [""]
assert changed(template, %{}, %{foo: true}) == [""]

template = "<%= Access.get(assigns, :foo) %>"
assert changed(template, %{foo: 123}, nil) == ["123"]
Expand Down Expand Up @@ -268,6 +271,21 @@ defmodule Phoenix.LiveView.EngineTest do
assert changed(template, new_changed_bar, old) == ["777"]
end

test "map access with non existing key" do
template = "<%= @map[:baz] || \"default\" %>"
old = %{map: %{foo: 123, bar: 456}}
new_augmented = %{map: %{foo: 123, bar: 456, baz: 789}}
new_changed_foo = %{map: %{foo: 321, bar: 456}}
new_changed_bar = %{map: %{foo: 123, bar: 654}}
assert changed(template, old, nil) == ["default"]
assert changed(template, old, %{}) == [nil]
assert changed(template, old, %{map: true}) == ["default"]
assert changed(template, new_augmented, old) == ["789"]
# no re-render when the key is still not present
assert changed(template, new_changed_foo, old) == [nil]
assert changed(template, new_changed_bar, old) == [nil]
end

test "renders dynamic with access tracking for forms" do
form1 = Phoenix.Component.to_form(%{"foo" => "bar"})
form2 = Phoenix.Component.to_form(%{"foo" => "bar", "baz" => "bat"})
Expand Down

0 comments on commit b9c8977

Please sign in to comment.