dphfox / Fusion

A modern reactive UI library, built specifically for Roblox and Luau.
https://elttob.uk/Fusion/
MIT License
594 stars 101 forks source link

Observer should allow for multiple state objects at once #258

Open funwolf7 opened 1 year ago

funwolf7 commented 1 year ago

Currently, it is difficult to have a piece of code run whenever one of multiple different state objects change.

Let's say you have two states, State1 and State2, and you want to run an function whenever either of them change.

The most basic way is to use two Observers and run the code whenever any of them change, however this causes some problems.

A current workaround is to create a Computed that calls use on all the state objects and returns something unique every time, then attaching an Observer to it. This gets rid of the problems as Computeds will only update once, after all their dependencies have updated.

Observer(Computed(function(use)
    use(State1)
    use(State2)
    return {}
end)):onChange(function()
    -- do whatever
end)

However this isn't an obvious solution, and has its own tedium of writing a use call for every state and returning a table. It is probably also less efficient than an official method would be.

Thus, I propose a way to have an observer take multiple state objects, and run the function only after all of them that will update actually update. I'm not sure what the best API implementation would be, but I'm sure there are plenty of elegant methods.

krypt102 commented 1 year ago

Why not just

Observer({state1, state2, ...}):onChange(...)

From what the computed example has, it would still update every time either one of the two states changes? Unless I'm not understanding lol

dphfox commented 1 year ago

This is definitely something I've thought about. I would quite like to unify the design of Observers with that of Computeds etc, but the historical problem has been that the previous automatic dependency manager was incompatible with code that could yield (which Observers are explicitly designed to support).

This might not be such a problem now that we have the new use() callbacks. This may be worth thinking about.

dphfox commented 1 year ago

Related to #4 - the design of Eventual also provisions for use callbacks in yielding contexts. The behaviour of these two objects should be aligned with respect to how dependencies are captured after the first yield.