liveview-native / liveview-client-swiftui

MIT License
372 stars 36 forks source link

[Bug]: Rendered assign in template element does not update when changed #1380

Closed jtormey closed 3 months ago

jtormey commented 3 months ago

What happened?

I have a particular element within an item in a list that is rendered using template. I pass the result of a function call (which receives an assign as an argument) to a component attr. The attr is rendered inside the component. On first render, it shows correctly. However, when the assign is updated, the template does not re-render the attr.

Other parts of the view re-render when they're supposed to with the updated assign. I have confirmed that the correct information is in the diff data structure received by the client.

The project is open source, the assign that isn't updating is here: https://github.com/jtormey/lax/blob/main/lib/lax_web/live/chat_live/chat_components.swiftui.ex#L75

Happy to provide more information if helpful.

Library Version

9fe36d4

Xcode Version

15.4

Swift Version

swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)

On which device or simulator are you running into the problem?

iPhone

Target Device Operating System Version

15

Relevant log output

No response

carson-katri commented 3 months ago

This looks like an issue with modifiers that have TextReference arguments (such as badge(_:)).

The Text element used by badge cannot respond to updates itself. Instead, the outer element containing the badge needs to setup an observer on that child element.

I'm not sure how to resolve this in the library yet, but there are a few alternative implementations that can work:

  1. Use a different badge(_:) clause The badge(AttributeReference<Int>) clause will properly respond to updates:
<Group style='badge(attr("count"))' count={@unread_count} />
  1. Update the outer element when the content changes. If you apply some attribute to the container element that updates alongside the Text content, it will trigger an update of the badge modifier content
<Group style="badge(:badge)" count={@unread_count}> <!-- the `count` here is just used to update the container `Group` -->
  <Text template="badge"><%= @unread_count %></Text>
</Group>
jtormey commented 3 months ago

I can confirm that both of these solutions resolve the issue, thank you!