v1.0.0
Components
Added second prop to components.
const Button = statelessComponent<{ id: string }, Op>((props, children) => (
button("button", props, children)
));
Button({ id: "button-id" },
"Click Me",
);
Custom areEqual
function
const View = statelessComponent<number, [number, number]>(
(a, b) => (
a + b[0] + b[1]
),
undefined,
shallowEqualArray,
);
View(1, [2, 3]);
Dirty Checking / Observables
Dirty checking API were redesigned to improve support for use cases with coarse-grained observable graphs and
mutable data structures.
New API for dirty checking is composable and can be used in stateless components.
useSelect()
hook were removed.- Added pull-based observables.
- Context is reimplemented with observables and it is now way much cheaper to dirty check.
Examples
Computed Values (lazy evaluation)
const a = observable(1);
const b = observable(2);
const sum = computed(() => watch(a) + watch(b));
const A = statelessComponent(() => div(_, _, watch(sum)()));
Basic selectors with immutable state
const STATE = { value: 1 };
const A = component((c) => {
const getValue = selector(() => STATE.value);
return () => div(_, _, watch(getValue)());
});
Memoized selector with immutable state
const STATE = { a: 1, b: 2 };
const A = component((c) => {
const getValue = selector((prev) => (
prev !== void 0 && prev.a === STATE.a && prev.b === STATE.b ? prev :
{ a: STATE.a, b: STATE.b, result: STATE.a + STATE.b };
));
return () => div(_, _, watch(getValue)());
});
Composition
const a = observable(1);
const A = component((c) => {
const getValue = memo((i) => computed(() => watch(a) + i));
return (i) => div(_, _, watch(getValue(i))());
});
Boolean DOM Attribute Values
Removed automagic conversion from boolean values to empty string. Correct attribute values should be specified
explicitly.
textContent=""
Optimization
This optimization has a quite noticeable impact in popular benchmarks. But in real applications, use cases that would benefit from this optimization will work significantly faster by wrapping lists into a transient DOM node.
Deep State Tracking
Deep state tracking optimization were removed. It is one of those optimizations that improve performance in benchmarks, but make it worse in real applications.
This optimization worked by updating node state flags during stack unwinding. It saved information about node subtree, so we could skip dirty checking and unmounting for subtrees that didn't have any stateful components. In applications decomposed into small components there will be many stateful components used as leaf nodes, so instead of optimizing, it will make dirty checking and reconciliation algorithms slightly slower. Also, this optimization were adding a lot of complexity to the reconciliation algorithm.
Simplified track by key algorithm
Instead of returning LIS indices, nodes that are part of LIS are now marked in the input array.
Events
Stop Propagation
Synthetic event handlers do not propagate events anymore. To propagate events, event handler should return
DispatchEvent.Propagate
value.
Move Events
Removed touch/mouse/pointer move events. Move event handlers usually attached when down event is triggered. To make sure that we don't lose any move events, we can't wait until next frame is rerendered, so move event handlers should be attached with native DOM api.
Server Side Rendering
Removed. Not interested in supporting this feature.