Skip to content

Commit b9c8977

Browse files
authored
change-track non existing keys in maps (#3584)
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`.
1 parent e2ec312 commit b9c8977

File tree

2 files changed

+19
-0
lines changed

2 files changed

+19
-0
lines changed

lib/phoenix_live_view/engine.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,6 +1299,7 @@ defmodule Phoenix.LiveView.Engine do
12991299
defp recur_changed_assign([], head, assigns, changed) do
13001300
case {assigns, changed} do
13011301
{%{^head => value}, %{^head => value}} -> false
1302+
{m1, m2} when not is_map_key(m1, head) and not is_map_key(m2, head) -> false
13021303
{_, %{^head => value}} when is_map(value) -> value
13031304
{_, _} -> true
13041305
end

test/phoenix_live_view/engine_test.exs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ defmodule Phoenix.LiveView.EngineTest do
172172
assert changed(template, %{foo: 123}, nil) == ["123"]
173173
assert changed(template, %{foo: 123}, %{}) == [nil]
174174
assert changed(template, %{foo: 123}, %{foo: true}) == ["123"]
175+
assert changed(template, %{}, %{}) == [nil]
176+
assert changed(template, %{}, %{foo: true}) == [""]
177+
assert changed(template, %{}, %{foo: true}) == [""]
175178

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

274+
test "map access with non existing key" do
275+
template = "<%= @map[:baz] || \"default\" %>"
276+
old = %{map: %{foo: 123, bar: 456}}
277+
new_augmented = %{map: %{foo: 123, bar: 456, baz: 789}}
278+
new_changed_foo = %{map: %{foo: 321, bar: 456}}
279+
new_changed_bar = %{map: %{foo: 123, bar: 654}}
280+
assert changed(template, old, nil) == ["default"]
281+
assert changed(template, old, %{}) == [nil]
282+
assert changed(template, old, %{map: true}) == ["default"]
283+
assert changed(template, new_augmented, old) == ["789"]
284+
# no re-render when the key is still not present
285+
assert changed(template, new_changed_foo, old) == [nil]
286+
assert changed(template, new_changed_bar, old) == [nil]
287+
end
288+
271289
test "renders dynamic with access tracking for forms" do
272290
form1 = Phoenix.Component.to_form(%{"foo" => "bar"})
273291
form2 = Phoenix.Component.to_form(%{"foo" => "bar", "baz" => "bat"})

0 commit comments

Comments
 (0)