Recently, we encountered a bug with some Stimulus code. We were trying to stream updates for a small partial and found that data only refreshed on the first update.
Here’s the code we were using:
Template:
1
2
3
4
<%= turbo_stream_from "revenue" %>
<div id="revenue">
<%= render partial: 'metrics/revenue', locals: { revenue: @revenue } %>
</div>
Model:
1
2
3
4
5
6
7
class Sale < ApplicationRecord
after_commit -> { broadcast_replace_to "revenue", partial: "metrics/revenue", locals: { revenue: Sale.total }, target: "revenue" }
def self.total
pluck(:amount).sum
end
end
broadcast_replace_to
is used to trigger the replace stream action. The documentation for Turbo actions is sparse but it’s reasonable to expect that this method replaces a DOM element with a new one. However, broadcast_replace_to
only updates a DOM element once. This causes a strange bug where the first model update triggers a page re-render but subsequent updates do not.
In the end, we fixed the bug by switching to update. Here’s the new model code:
1
2
3
class Sale < ApplicationRecord
after_commit -> { broadcast_update_to "revenue", partial: "metrics/revenue", locals: { revenue: Sale.total }, target: "revenue" }
end
Hopefully this will save you some debugging time!