reactive_component 0.9.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 111726d46e0cac07d669edebc52f2d7e5e2ee05f5b94f7b766d2b400d647f196
4
- data.tar.gz: d0cbaadaddb9b4b2c362ba2036e1f8a9efc5a67665a7673d9694134b1a439f64
3
+ metadata.gz: b5392838b8ed189cab22600b11b26eaa10215f601dd18294a4070febd9d88fbc
4
+ data.tar.gz: ed5fc1b4fb9c8e41ca0e717481323655b04b31bd4c94eb7ae011d4e05452b881
5
5
  SHA512:
6
- metadata.gz: b7df34cf75a7a5b83a6ab9d7c98995dcb5bed86b2a67269ab10ca00580af0b769d6aaba0ad37aa861740c4a7e2d242ae851dda561866a76858ae9ad022795f8d
7
- data.tar.gz: 32e7b0d49b496c2fff61011751c13d66de283c0c661b6de755da3b2a8919739b6f04861f1de49f9e66c049147a30a960e9436403012ac48f954de0b4a1830d7d
6
+ metadata.gz: bc1903d993c6504bccd2235175c131287589437461991084dfd93f6124f806de5589a669581bc9e3a34feac4fd5ad5f251131cabe498e5ad4218ade2db225574
7
+ data.tar.gz: 84a9b85096b7838863837ed0fac03be89394ceef37a24484a1425a9643f707dc120204a8c8b9bf90f2f5645e5d18ce87f04e0d4603a6a6c218f31f16b85d1bc1
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.1] - 2026-09-17
4
+
5
+ ### Changed
6
+ - The renderer logs every render and update only when `ReactiveComponent.debug`
7
+ is on, which it reads from the `data-reactive-debug` attribute already on the
8
+ wrapper. It used to log everywhere, production included, unless a
9
+ `devToolbar:debug` key in `localStorage` was set to the string `"false"`.
10
+ - A client-state change on a notify component that has no data yet asks the
11
+ server to render it instead of doing nothing, and an update request carries
12
+ the state the component is in now rather than the one the page was built
13
+ with.
14
+ - A notify wrapper with client state no longer embeds its initial data payload.
15
+ It asks the server to render it, so the attribute was the page a second time,
16
+ carrying every branch of every extracted expression. A push wrapper keeps it:
17
+ it renders from that payload until the first broadcast arrives.
18
+
3
19
  ## [0.9.0] - 2026-09-17
4
20
 
5
21
  ### Added
@@ -3,11 +3,6 @@ import { createConsumer } from "@rails/actioncable"
3
3
  import { compileTemplate, decompress, morphElement, buildActionBody, routeMessage, duplicateIds, strictData } from "reactive_component/lib/reactive_renderer_utils"
4
4
 
5
5
  const consumer = createConsumer()
6
- const log = (...args) => {
7
- if (localStorage.getItem("devToolbar:debug") !== "false") {
8
- console.log("[reactive-renderer]", ...args)
9
- }
10
- }
11
6
 
12
7
  function findSubscription(streamValue) {
13
8
  const identifier = JSON.stringify({ channel: "ReactiveComponent::Channel", signed_stream_name: streamValue })
@@ -113,6 +108,14 @@ export default class extends Controller {
113
108
  this.element.removeAttribute("data-reactive-renderer-connected")
114
109
  }
115
110
 
111
+ // ReactiveComponent.debug marks the wrapper, so the gem is quiet unless the
112
+ // app turns debugging on server-side.
113
+ log(...args) {
114
+ if (this.element.hasAttribute("data-reactive-debug")) {
115
+ console.log("[reactive-renderer]", ...args)
116
+ }
117
+ }
118
+
116
119
  resolveTemplate() {
117
120
  if (this.hasTemplateValue) return this.templateValue
118
121
 
@@ -129,18 +132,18 @@ export default class extends Controller {
129
132
 
130
133
  switch (route.type) {
131
134
  case "render":
132
- log("render", this.element.id, route.data)
135
+ this.log("render", this.element.id, route.data)
133
136
  this.lastServerData = route.data
134
137
  if (this.renderFn) this.render({ ...route.data, ...this.clientState })
135
138
  break
136
139
 
137
140
  case "request_update":
138
- log("update", this.element.id, { action: message.action, strategy: "notify" })
141
+ this.log("update", this.element.id, { action: message.action, strategy: "notify" })
139
142
  this.requestUpdate()
140
143
  break
141
144
 
142
145
  case "update":
143
- log("update", this.element.id, route.data)
146
+ this.log("update", this.element.id, route.data)
144
147
  this.lastServerData = route.data
145
148
  if (this.renderFn) this.render({ ...route.data, ...this.clientState })
146
149
  this.element.dispatchEvent(new CustomEvent("reactive-renderer:updated", {
@@ -168,7 +171,9 @@ export default class extends Controller {
168
171
  component: this.componentValue,
169
172
  sgid: this.sgidValue,
170
173
  dom_id: this.element.id,
171
- params: this.paramsValue
174
+ // The channel reads client state off params, so the server renders the
175
+ // state the component is in now, not the one the page was built with.
176
+ params: { ...this.paramsValue, ...this.clientState }
172
177
  })
173
178
  }, 50)
174
179
  }
@@ -262,16 +267,23 @@ export default class extends Controller {
262
267
  changed = true
263
268
  }
264
269
  }
265
- if (changed && ctrl.lastServerData && ctrl.renderFn) {
266
- requestAnimationFrame(() => ctrl.render({ ...ctrl.lastServerData, ...ctrl.clientState }))
267
- }
270
+ if (changed) ctrl.rerender()
268
271
  })
269
272
  }
270
273
  }
271
274
 
272
275
  Object.assign(this.clientState, updates)
276
+ this.rerender()
277
+ }
278
+
279
+ // A push component holds the data it needs. A notify one may not have any
280
+ // yet, its payload arrives on request, so a state change asks for it rather
281
+ // than leaving the click with nothing to show.
282
+ rerender() {
273
283
  if (this.lastServerData && this.renderFn) {
274
284
  requestAnimationFrame(() => this.render({ ...this.lastServerData, ...this.clientState }))
285
+ } else if (this.strategyValue === "notify") {
286
+ this.requestUpdate()
275
287
  }
276
288
  }
277
289
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReactiveComponent
4
- VERSION = '0.9.0'
4
+ VERSION = '0.9.1'
5
5
  end
@@ -45,8 +45,15 @@ module ReactiveComponent
45
45
 
46
46
  if client_state
47
47
  attrs << %(data-reactive-renderer-state-value="#{ERB::Util.html_escape(client_state.to_json)}")
48
- initial_data = component_class.build_data(record, **client_state.symbolize_keys)
49
- attrs << %(data-reactive-renderer-data-value="#{ERB::Util.html_escape(initial_data.to_json)}")
48
+
49
+ # A push wrapper renders from this payload until the first broadcast
50
+ # arrives. A notify one asks the server for its data instead, so the
51
+ # attribute would be the page a second time, both branches of every
52
+ # extracted expression included.
53
+ unless strategy.to_s == 'notify'
54
+ initial_data = component_class.build_data(record, **client_state.symbolize_keys)
55
+ attrs << %(data-reactive-renderer-data-value="#{ERB::Util.html_escape(initial_data.to_json)}")
56
+ end
50
57
  end
51
58
 
52
59
  attrs << %(data-reactive-renderer-strategy-value="#{strategy}") if strategy
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reactive_component
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Przemyslaw Lusar