viridia / quill_v1

Reactive UI framework for Bevy game engine
MIT License
60 stars 7 forks source link

ViewState modification tracking #2

Closed viridia closed 9 months ago

viridia commented 10 months ago

ViewStates track whether the dependencies of a view have been modified. There are several things that can trigger a build:

Views are automatically memoizing. This is like Solid and unlike React. In React, re-rendering a parent automatically re-renders its children unless you wrap the component in memo(). Note: we can revisit this decision.

There is also the issue of fine-grained memoization. For example, when tracking a resource for changes, you may only care about one property being changed, you don't want to re-render if anything else changes. We don't have to address this now, it's something to think about for the future.

Like Solid, all tracking is self-erasing / self-healing. All listeners are one-shot, there are no persistent subscriptions. Instead, the rebuild process re-subscribes the listeners as a side-effect.

The way this works is that the space of subscriptions is divided into "tracking contexts". A tracking context has a list of subscriptions and a reaction. For views, there's a tracking context per view state.

When a subscription is triggered, it does not immediately invoke the reaction, but marks the tracking context as modified. The "update" system does the following:

Note that triggering a rebuild of a parent may also cause a rebuild of its children. This might cause build to be called twice if both parent and child are marked as modified. To avoid this, we'll want some way to (a) have parents build before children, and (b) mark the children as unmodified when they are rebuild, even if the rebuild was caused by something other than the child's reaction.

Dropping / despawning: there are several cases where view states can be dropped:

In these cases, we'll want to ensure that there are no remaining subscriptions for the view state, because we don't want to run the reaction for the despawned elements.

viridia commented 10 months ago

There's been a lot of progress on this, although much remains to be done.

Despawning of View is done by the raze() method. Updating in response to resource changes works, but other kinds of updates are not yet tracked.