Automatic memoization separates a local client state's reader and setter into different React state instances. A button that renders its own client-state value does not visibly update when clicked.
Reproduced on main commit 31d57490470228c08595e73bcae1f86703880e26 and on 565dd92bfbb26c86d064e7bebfaf47321414c7a0.
import reflex as rx
count = rx._x.client_state("local_count", default=0, global_ref=False)
def index():
return rx.el.button(
count.value,
on_click=count.set_value(count.value + 1),
id="counter",
)
app = rx.App()
app.add_page(index)
Run the app, wait for hydration, and click the button. It keeps displaying 0; no browser error is reported. The expected text is 1, then 2 on the next click.
The generated Button memo has useState(0) and calls its own setter. Its text is rendered by a separate Bare memo with another useState(0). The setter therefore never updates the state that the text reads.
For comparison, rendering the value as an element prop keeps it in the same memo as the event handler and works:
rx.el.input(
type="button",
value=count.value,
on_click=count.set_value(count.value + 1),
)
Validated both cases through real clicks and DOM assertions in Chrome. Please keep a local client-state read and its setter in the same hook scope when memoizing children.
Automatic memoization separates a local client state's reader and setter into different React state instances. A button that renders its own client-state value does not visibly update when clicked.
Reproduced on main commit
31d57490470228c08595e73bcae1f86703880e26and on565dd92bfbb26c86d064e7bebfaf47321414c7a0.Run the app, wait for hydration, and click the button. It keeps displaying
0; no browser error is reported. The expected text is1, then2on the next click.The generated
Buttonmemo hasuseState(0)and calls its own setter. Its text is rendered by a separateBarememo with anotheruseState(0). The setter therefore never updates the state that the text reads.For comparison, rendering the value as an element prop keeps it in the same memo as the event handler and works:
Validated both cases through real clicks and DOM assertions in Chrome. Please keep a local client-state read and its setter in the same hook scope when memoizing children.