Skip to content

Commit

Permalink
fix: make sure the reactive listeners are attached as early as possible
Browse files Browse the repository at this point in the history
before we would execute the use_effect that attaches event listeners
for reactive variables after those of users. Now, we execute it
before users.
Before this caused setting of reactive variables in a use_effect to
not re-render the current component.
  • Loading branch information
maartenbreddels committed Jun 23, 2023
1 parent 99036cb commit bda142c
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 3 deletions.
6 changes: 3 additions & 3 deletions solara/lab/toestand.py
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,6 @@ def set(self, value):
class AutoSubscribeContextManager:
# a render loop might trigger a new render loop of a differtent render context
# so we want to save, and restore the current reactive_used
reactive_used_before: Optional[Set[ValueBase]] = None
reactive_used: Optional[Set[ValueBase]] = None
reactive_added_previous_run: Optional[Set[ValueBase]] = None
subscribed: Dict[ValueBase, Callable]
Expand All @@ -499,7 +498,6 @@ def __enter__(self):
self.reactive_used_before = thread_local.reactive_used
self.reactive_used = thread_local.reactive_used = set()

def __exit__(self, exc_type, exc_val, exc_tb):
assert thread_local.reactive_used is self.reactive_used, f"{hex(id(thread_local.reactive_used))} vs {hex(id(self.reactive_used))}"
_, set_counter = solara.use_state(0, key="auto_subscribe_force_update_counter")

Expand Down Expand Up @@ -544,7 +542,9 @@ def cleanup():
return cleanup

solara.use_effect(on_close, [])
thread_local.reactive_used = self.reactive_used_before

def __exit__(self, exc_type, exc_val, exc_tb):
pass


# alias for compatibility
Expand Down
19 changes: 19 additions & 0 deletions tests/unit/lab/toestand_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1036,3 +1036,22 @@ def Test():
assert mock2.call_count == 1

rc.close()


def test_reactive_var_in_use_effect():

var = Reactive(1)

@solara.component
def Test():
def modify():
var.value = 2

solara.use_effect(modify)
# note: just pass the value, not the reactive variable
# otherwise the test passes. It is important *this*
# component listens to the reactive variable.
return solara.IntSlider("test", value=var.value)

box, rc = solara.render(Test(), handle_error=False)
assert rc.find(v.Slider).widget.v_model == 2

0 comments on commit bda142c

Please sign in to comment.