flooks v4, auto optimize, update on demand. The simplest React Hooks state manager
Problem of state management
In React Hooks state management, usually encounter the problem of linkage update:
One module updated, all components that consume this module will re-render, even if the updated state not used in the component.
For example, model = {a: 1, b: 2, fn: () => {} }
, call setModel({ a: 2 })
, components that only use b
will also re-render. In theory, components only use fn
function should never be updated by setModel()
, but also re-rendered.
If don’t want to update by association, we have to split the data into pieces — for example, React.useState()
jotai
etc., is the kind of "metadata" idea. There is another "modularity" idea, such as React.useReducer()
, which hopes to put the data of one module together.
Using “metadata” will deviate from the original intention of putting data together. Using “modularity” will face the problem of components linkage update.
In the traditional class components project uses Redux, react-redux
realizes the performance optimization of components linkage update. While the pure React Hooks project only uses the state manager implemented by Hooks, there is not a good solution.
Introducing flooks v4
flooks is a state manager dedicated to React Hooks, with an extremely simple API. Which supports modularity and intercommunication between modules, and may be the simplest one.
→ https://github.com/nanxiaobei/flooks
The API of flooks v3 is like this:
const counter = (now) => ({
count: 0,
add() {
const { count } = now();
now({ count: count + 1 });
},
});function Counter() {
const { count, add } = useModel(counter, ['count']); // use deps to know injected state
return <div />;
}
flooks v4 made some updates:
const counter = ({ get, set }) => ({
count: 0,
add() {
const { count } = get(); // get
set({ count: count + 1 }); // set
},
});function Counter() {
const { count, add } = useModel(counter); // no need for deps
return <div />;
}
The main changes are:
now
is divided intoget
andset
, to make code clearer- No need to pass the deps for re-render control
set
supports function styleset(state => ({ count: state.count + 1 })
In addition, more importantly, flooks v4 completely rewrites the core update logic behind, and completely solves the problem of linkage update of the “modularity” scheme. The fine control of updating has been realized.
Re-render auto optimization
Through proxy
, flooks realizes a gorgeous auto optimization, re-render completely on demand, when React is truly "react".
useModel(someModel)
returns a proxy, only actually used data will be injected into the component. If not used, just not injected.
So there is no need to use deps, because useModel()
can now know which data will be destructure and use, and only update the used data.
Only functions never trigger re-render
const { fn1, fn2 } = useModel(someModel); // A componentconst { b, setB } = useModel(someModel); // B component
setB(); // A no re-render
If only functions used in A, others update won’t trigger A re-render.
Unused state never trigger re-render
const { a } = useModel(someModel); // A componentconst { b, setB } = useModel(someModel); // B component
setB(); // A no re-render
If some state not used in A, others update won’t trigger A re-render.
Unused loading never trigger re-render
const { someFn } = useModel(someModel); // A component
someFn(); // no someFn.loading, no extra re-render
If someFn.loading
not used in A, someFn()
won't trigger extra re-render.
If someFn
is async, with normal loading solutions, even someFn.loading
is not used, re-render will trigger at least twice (turn true
then false
). However, with flooks, no invisible loading updates, if someFn.loading
is not used.
Truly “modularity”
Above, flooks v4 truly realizes the “modularity” for the React Hooks state management.
That is, you can put the data of the same module in one place, convenient for unified manage, and no need to worry about partial update triggering linkage update. The update performed entirely on demand. Only the used data trigger, and the unused data, even someFn.loading
, will not inject into the component.
What is written in code will be updated, and what is not written will not exist at all, so no need to worry about update.
Everything is so intuitive, no other annoying concepts.
It’s over
flooks v4, if you like, welcome to ✰