React(ive) state management
Enter Observables
React's reactivity
Reactivity in real life
Reactivity in modern web
Heinrich Apfelmus
"The essence of a functional reactive programming is to specify the dynamic behavior of the value completely at the time of declaration."
Reactivity refers to how an application automatically updates the UI whenever application state changes.
Why so Reactive?
Automatic Updates
Improved DX
Enhanced UX
Reduced Code Complexity
03
02
04
01
Coerced v.s. Fine-grained Reactivity
- Simpler approach
- Entire UI re-renders whenever the state changes
- More granular control over UI updates
- Updates the specific parts of the UI that are affected by the state change
Enter Signals
Nikola Mitrović
Development Lead & Technical Architect
Vega IT
Novi Sad, Serbia
Tech Speaker
State management challenges
Scalability
Predictability
Performance
Maintainability
02
04
Developer Experience
03
01
05
Ratings
- Excellent 🚀
- Very good 👍
- Ok 👌
- Meh 😒
- Would not recommend 👎
React
React
Surgical precision 👎
Consistent state 😒
Performance 👎
Easier mental model 😒
Clean dev experience 🚀🚀
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const incrementCount = () => {
setCount(count + 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={incrementCount}>Increment</button>
</div>
);
}
export default Counter;
SolidJS
SolidJS
Surgical precision 🚀
Consistent state 🚀
Performance 🚀🚀🚀
Easier mental model 🚀🚀
Clean dev experience 👍
import { createSignal, onCleanup } from 'solid-js';
function Counter() {
const [count, setCount] = createSignal(0);
const increment = () => setCount(count() + 1);
// Clean up (e.g., clearing intervals) on component unmount
onCleanup(() => console.log('Counter component unmounted!'));
return (
<div>
<button onClick={increment}>Count: {count()}</button>
</div>
);
}
Enter RxJS
RxJS is a library that enables reactive programming in JavaScript. This means working with data streams and events in a more streamlined and declarative manner.
Observables at the Core
The fundamental building block of RxJS is the Observable. An Observable represents a stream of values (events or data) that can arrive over time.
React-RxJS
React-RxJS
Targeted re-renders 🚀
Consistent state 🚀
Performance 😒
Easier mental model 👍
Clean dev experience 😒
import { bind } from "@react-rxjs/core";
import { createSignal } from "@react-rxjs/utils";
import { shareReplay, takeWhile } from "rxjs/operators";
const [counterChange$, setCounter] = createSignal<number>();
const counterLimit$ = counterChange$.pipe(
takeWhile((value) => value < 10),
)
const [useCounter] = bind(
counterChange$.pipe(
shareReplay(1)
),
0
);
export { useCounter, setCounter };
Entry point to
React-RxJS
Recipe request
gRPC streaming
Server URL
RPC method
Request message
Pull v.s. push
React-RxJS docs
"Historically, React uses a pull-based architecture. On the other hand, RxJS uses a push-based approach, where you declaratively define streams and their relationships, and RxJS will propagate every change from one stream to the next one. React-RxJS bridges the gap between these two behaviors."
Enter MobX
Signal-like, targeted re-rendering approach
Minimal boilerplate + Flexibility + DevTools
Simplicity
Performance
MobX
Enter MobX
import { action, makeObservable, observable } from 'mobx';
class AppState {
constructor() {
makeObservable(this); // Enable MobX observability
}
@observable count = 0;
@action increment() {
this.count++;
}
}
export const appState = new AppState();
Surgical precision 🚀
Consistent state 🚀
Performance 👍
Easier mental model 😒
Clean dev experience 🚀
MobX in React 19 (with Compiler)
Some libraries hack up React internals to make signals and fine-grained reactivity work, which often doesn’t work on all platforms and may break if React internals change.
React 19 - Forget Compiler
How much did we move the needle?
Virtual DOM
Zone.js
Dirty Checking
Enter Legend State Observables
Fine-grained reactivity 🔥
No boilerplate 👍
Designed for maximum performance and scalability ⚡️
Super small at 4kb 🐥
Super easy to use 😌
Legend State
Legend State
import { Memo } from "@legendapp/state/react";
import { count$ } from "../state";
const count$ = observable(0);
export const BasicCounter = () => {
const handleClick = () => count$.set((v) => v + 1);
return (
<div>
<div>
Legend Count: <Memo>{count$}</Memo>
</div>
<button onClick={handleClick}>Add count</button>
</div>
);
};
Surgical precision 🚀
Consistent state 🚀
Performance 🚀
Easier mental model 🚀🚀
Clean dev experience 👍
Resources
https://www.builder.io/blog/unified-reactivity-theory
https://www.builder.io/blog/history-of-reactivity
https://www.youtube.com/watch?v=R5AcOtxIdMk
https://www.youtube.com/watch?v=cPVbfiAEbac
https://www.youtube.com/watch?v=l-0fKa0w4ps
https://dev.to/ryansolid/building-a-reactive-library-from-scratch-1i0p
https://legendapp.com/open-source/legend-state/
TanStack Query, Meet RxJS: Building Your Own TanStack Query with Angular & RxJS
Thank you!
n.mitrovic@vegait.rs
You can find me at
Link to the slides
https://github.com/nmitrovic92/reactive-state-managements
(React)ive state management
By nmitrovic
(React)ive state management
- 240