Pyroxenium / Basalt

A UI Framework for CC:Tweaked
MIT License
164 stars 28 forks source link

Reactive Props V2 #71

Closed thesabinelim closed 1 year ago

thesabinelim commented 1 year ago

The original reactive props system was based on a naive implementation (a hard-coded pattern match for the shared and props tables in a prop and a metatable to detect reads/writes on the shared table) that was proving difficult to extend further. This PR rebuilds the reaction system to be based on a new primitive, basalt.reactive, which is not coupled to the environment. It also does away with the naive pattern matching. Any global variable can now be accessed in a reactive prop. Additionally, reactive props are now full Lua expressions, which are computed to return a value. This makes it possible to do things like this:

<script>
  local basalt = require("basalt")
  getCount, setCount = basalt.reactive(0)
</script>

<button text={"Times clicked: " .. getCount()}>
  <onClick>
    setCount(getCount() + 1)
  </onClick>
</button>

<label text={"Times clicked * 2 = " .. getCount() * 2} />

Internally, this works in much the same way that Signals work in Solid.js. We populate a list of observers for a reactive value on the first pass render, based on calls to their respective get functions. A subsequent call of the set function will then update all these observers.

Other changes