Technology
Episode 23 - Building a minimal reactive framework
In this episode, Minkou Gegef explores the fundamentals of building a minimal reactive framework, focusing on concepts like signals, state management, and component composition. Listeners will gain in...
Episode 23 - Building a minimal reactive framework
Technology •
0:00 / 0:00
Interactive Transcript
spk_0
Welcome to the programming podcast.
spk_0
Here you can learn about computer science concepts in a brief and accessible way.
spk_0
I'm your host, Minkou Gegef.
spk_0
Hello everyone.
spk_0
In today's episode I'm hoping to give you a high level intuition on how reactive frameworks work.
spk_0
This episode is inspired by a blog post that I wrote about a week, a week and a half ago,
spk_0
on how you can implement your own very simple reactive framework with fine-grained reactivity and
spk_0
signals in only 200 lines of code. And this implementation includes the components model of the
spk_0
framework. It allows you to build components. It includes the rendering as well as the
spk_0
signal's implementation itself. So it is pretty simple and it will enable you to build pretty much
spk_0
any application out there. Okay, this is going to just give you an intuition. This is not exactly
spk_0
how frameworks such as Angular, Solid or React work. They have a variety of different
spk_0
reactivity models and variations of these reactivity models. But I'm hoping to be close enough
spk_0
so that you can understand some of the essential differences between the different
spk_0
underlying concepts in a web framework. So just let's say dynamic and static parts of the view,
spk_0
reactivity systems states and so on and so forth. So today we're going to look at a couple of
spk_0
concepts. First we're going to make a very quick recap of signals and put them into the context
spk_0
of a web framework. After that, we're going to briefly talk about state management and how
spk_0
signals can support us in managing state inside of our components. We're going to briefly discuss
spk_0
static versus dynamic parts of the view because this is something that many frameworks such as
spk_0
Angular, Solid.js, they create a distinction between these two. And we're going to briefly touch on
spk_0
Trollflow and how we can implement it just by using signals. So first, let's make a very quick
spk_0
recap about signals. If you haven't listened to the previous episodes that was entirely dedicated
spk_0
on signals in its only 10 minutes, I'll recommend you to have a look at it. Just listen to it.
spk_0
But if you haven't, well, the signal is just a wrapper around a primitive or non-primitive value.
spk_0
That's pretty much what a signal is. We can get this value or we can replace it with a new value.
spk_0
We can set it. Additionally, we can use a concept called effect. And effect is just a function that
spk_0
accepts a callback. When we read a signal inside of this callback, the effect remembers that we
spk_0
are interested in this signal or the signal remembers that they're interested in this effect.
spk_0
So anytime when we update the signal, we're going to invoke the callback that we have passed to the
spk_0
effect. That's all you need to know about signals. That there are wrappers around values. We can
spk_0
set them. We can read them. And when we read them inside of an effect, every time when we set
spk_0
their value, the effect will be invoked. That's all. Now something cool about signals is that they can
spk_0
be really great containers of the state inside of our applications. Imagine we have a toggle component,
spk_0
like a component which allows us to toggle its content. We can let's say make it visible or invisible.
spk_0
Or we can represent this very easily using a signal, which is a Boolean value. Let's say visible,
spk_0
which by default is, let's say true. And when we toggle the value, we're going to update the signal
spk_0
and make it invisible. If we read the signal inside of an effect, every time when we toggle the value,
spk_0
the effect is going to be invoked. So we can perform a certain action. This action could be anything
spk_0
you want. It could be some complicated calculation or it could be just updating the DOM.
spk_0
So inside of this callback, inside of this effect, when we read the visual state or the visibility
spk_0
state of the content, we can perform an action. Let's say we have the content of this component.
spk_0
When we read the visible signal, if the visible signals value is true, we can just set the inner HTML
spk_0
of the host element or the element of our component and visualize this content. When the value
spk_0
of visible is false, we can just delete it or like set its display in none or do whatever we want.
spk_0
So that's on a high level how we can take advantage of signals in order to manage the state
spk_0
in our applications and make the framework reactive. What does a web framework consist of?
spk_0
Well, web framework consists usually of components and we can compose these components in order to
spk_0
create the user interface of our applications. Inside of this components, we'll keep state and we
spk_0
would wrap the state in signals so that we can notify the framework when the state has changed.
spk_0
And from there on, the framework can use an effect in order to react to this change and update the view.
spk_0
Something interesting about the views is that they need to be composable. You need to be able to
spk_0
compose components into more complicated components. Let's say you are building a scheduler.
spk_0
Well, in the scheduler, you most likely need a bunch of buttons. You'll need tables in order to
spk_0
visualize the different events that are happening throughout the week. You need variety of different
spk_0
components that you need to compose together. This is the composites design pattern that we have
spk_0
from the book of the Ganga 4. And it is an important property of any component model out there.
spk_0
We can compose components by building them into one another. Additionally, we can use
spk_0
control flow or some kind of like special more privileged components that are coming directly from
spk_0
the framework. In different frameworks, we have the control flow being either a native feature
spk_0
of the templating system or the language, for example, in JSX. The control flow is just part of
spk_0
the language. You're just reusing the JavaScript control flow and very often using the standard operator.
spk_0
In framework, such as the Angular or Svelte, the control flow is part of the templating system.
spk_0
See a very first class citizen in the framework functionality. And usually the reason for this is that
spk_0
the control flow needs to have some special understanding of your application.
spk_0
If we're building a web framework from scratch just by using signals,
spk_0
we may want to embed the control flow instead of our framework as well. Let's look at a very
spk_0
simple example of how we can take advantage of the control flow. So if we have an if statement
spk_0
within our templating system, it is going to work very similarly to this toggle component that I
spk_0
described just a couple of minutes ago. If the condition of this statement is true, this means that
spk_0
we would like to render a particular part of the view. If this falls, we would like to remove it
spk_0
from the view. Meaning that we can implement if statement very easily, we can implement it just
spk_0
by using effects and assuming that the condition of this statement is a signal. Instead of the effect,
spk_0
we can read the result of the effect and we can respectively render or remove this particular part
spk_0
of the view. Other parts of the control flow such as let's say a four statement would work very
spk_0
similar. We would read the collection, which we're assuming is coming to us as a signal. And once we
spk_0
get this collection, we're going to trade over the individual items and render them one by one.
spk_0
Real real world web frameworks would not work exactly that way because we can't re-run
spk_0
the collection every time when we receive an update. Very often, we update only one or just a couple
spk_0
of items from this collection. It's not worth just destroying the whole world and re-randering
spk_0
the collection from scratch. What we would do in framework such as Angular, React, and others
spk_0
is to implement some kind of a different logic. That's why often the individual items in our
spk_0
collections, they have keys or track by in Angular, which allows you to give the two different
spk_0
collections, figure out what exactly changed and only re-run the real differences. But the basic
spk_0
implementation of control flow can just use signals and effects. And that's pretty much it.
spk_0
There is one more piece that I'd like us to look into. And it is how do you update individual
spk_0
properties or individual, like let's say text by using signals in a reactive framework?
spk_0
You can approach a problem in a very similar way. If you would like to update text, there is
spk_0
some dynamic value that could change. Let's say the user name or we have a counter and on every
spk_0
next iteration who would like to update this counter with its next value. All you need to do here is
spk_0
just use a text note. You can just wrap reading the signal that is representing the counter instead
spk_0
of an effect. And every time when the counter changes, we would like to update the value of the text
spk_0
note just by setting the value of the text note, which means that we will need to have the text
spk_0
note available within the effects function. Updating a property or an attribute of a particular HTML
spk_0
element will work exactly the same way. We just need a reference to this HTML element. We need to
spk_0
know which property or attribute will be updating and when the effect, excuse me, when the signal
spk_0
that we have bound to this particular attribute changes, we'll just get its value, read its value
spk_0
in the effect and update it. I know this tool may sound a little bit too abstract. That's why I
spk_0
have provided this very simple implementation to the framework that I mentioned on just about
spk_0
200 lines of code that you can review on your own. I promise implementation is probably
spk_0
significantly simpler that you don't anticipate. We have just one render function that knows how to
spk_0
render these individual notes in the view. And for some special notes that rely on signals,
spk_0
such as control flow, it creates effects so that every single time when we change the value of
spk_0
the signal, we can react to this change and update the view. So in the last couple of minutes,
spk_0
I'd like to discuss how we can implement the rendering functionality in this hypothetical
spk_0
framework because it is a pretty interesting algorithm and it shows us how exactly we separate
spk_0
the static versus dynamic parts of the template. Let's say that in our component, we have a bunch
spk_0
of different HTML elements and inside of one of them, we have a binding. While these HTML elements
spk_0
are going to be the static part of the view and the dynamic part of the view is going to be this
spk_0
binding, this expression that is coming from JavaScript. Additionally, inside of the
spk_0
view of this component, we need to be able to compose different components, which means that
spk_0
we're going to create a tree-like structure. We're going to have a component tree, which is the
spk_0
composition of all the components, and inside of every single one of these components, we're going
spk_0
to have some kind of a view or a template that is a composition of different notes. They could be
spk_0
HTML elements or text notes or anything else. Actually, that's pretty much the option. They could
spk_0
be HTML elements, text notes, comment notes. They could be just different types of DOM notes.
spk_0
Meaning that our rendering algorithm needs to be recursive. It needs to know how to render a tree.
spk_0
So it's going to start from top to bottom and for every single node, we're going to render the
spk_0
node and traverse its children. And for each one of their children, we're going to render them using
spk_0
the exact same algorithm. The nodes could be of different type. They could be just static HTML
spk_0
notes, or they could be dynamic notes, such as let's say conditional statements or iterators or
spk_0
like some kind of four loops. They could be also in between. We can have static HTML nodes that
spk_0
have some dynamic parts. Let's say individual attributes that could be dependent on the value of
spk_0
a signal. So in this case, we're going to render the individual static parts just by using
spk_0
document.create element, specifying the name of the element, and that's it. Let's say
spk_0
though that the content of this specific HTML element is dynamic. Let's say it's text content is
spk_0
dynamic. Or in this case, we can create an effect inside of this effect. We can
spk_0
hold a reference to the HTML element and we can read the value that the element's content
spk_0
depends on. So every time when we change the value of the signal that the content of the
spk_0
DOM node depends on, we can update the inner HTML or the inner text of this particular DOM node.
spk_0
We can apply the exact same thing to attributes as well. Let's say we have dynamic styles.
spk_0
We can use CSS in JavaScript and just have a string that represents the styles of this particular
spk_0
DOM node. Well, we can keep a reference to this DOM node inside of
spk_0
an effect. And every time when the signal representing the styles of this DOM node changes,
spk_0
we can just use elements.styles equals to the string that is produced by this particular signal.
spk_0
This is pretty much how a reactive framework would work by using this very simple primitive code
spk_0
signal. We're going to keep the state inside of our application within signals and we're going to
spk_0
propagate changes in the state with effects. In this particular model, we are using signals for both
spk_0
notifying the framework that something has changed and also telling the framework where exactly
spk_0
the state that changed this, which attributes was affected or which part of the view.
spk_0
In many other systems, we have an alternative approach. Let's say in systems such as React,
spk_0
you would notify that something has changed and from there the framework is responsible for
spk_0
figuring out how this thing changed. In Angular nowadays with signals instead of
spk_0
getting blind notification that something has changed potentially in the application,
spk_0
now go figure out what signals are notifying us that something changed in this particular
spk_0
component. Go check this component, update its view so that we can propagate the changes and
spk_0
synchronize the view state with the view. That's pretty much everything that I wanted to share today.
spk_0
We cover a lot in about 10-15 minutes. We discussed briefly what signals are,
spk_0
because these wrappers allow us to track changes in the Rob values over time. We discuss how we can
spk_0
build a very simple framework by using signals and effects, tracking the changed values
spk_0
instead of effects from there taking them and updating the corresponding DOM nodes. That's pretty
spk_0
much how it is. We discussed that composition of components. It's what represents our view model
spk_0
and we briefly touched on a DOM on a component rendering algorithm that is recursive and can
spk_0
track the dynamic and static values. The dynamic values that correspond to certain bindings
spk_0
that we can implement with signals and effects and static values that are just simple DOM nodes
spk_0
that we render into the browser. Well, I hold this episode was useful and if you would like to
spk_0
learn more about how you can implement your own simple framework, make sure you check my blog.
spk_0
You can find all the resources at podcast.mgachive.com. Thank you and until next time.
spk_0
You can follow me on social media at mgachive.mgchtv.
spk_0
For resources and recordings are also available at podcast.mgachive.com. Thank you for listening.
Topics Covered
reactive frameworks
computer science concepts
signals in programming
state management
dynamic vs static views
web framework components
control flow in frameworks
implementing reactive frameworks
Minkou Gegef podcast
building components with signals
effects in programming
composability in components
HTML element rendering
JavaScript control flow
user interface design