@shined/react-use
serves as a basic underlying tool library where performance is paramount. To ensure flexibility and richness of features while minimizing performance overhead as much as possible, we have introduced the concept of "Dependencies Collection".
The idea of dependency collection originally comes from SWR, based on which we have made some improvements and optimizations.
Many Hooks internally manage and return a lot of states. Users may only need one or some of these states, but any change in state causes re-rendering, leading to unnecessary performance overhead.
For instance, in @shined/react-use
there's a useQuery
, which, for implementing numerous feature characteristics, returns multiple states including but not limited to data
, loading
, error
, etc. Normally, regardless of whether the returned states are used, any change in the corresponding state causes internal calls like setState(loading)
to update the state.
This operation logic is not problematic in itself. The problem arises when updates occur despite the user not actually using some of the states, leading to unnecessary rendering overhead and significantly reducing rendering performance.
In certain scenarios (as above), we might only need one of the states, such as loading
, and not the other states. To achieve this, we introduced the concept of dependency collection, which is imperceptible to users but can significantly enhance performance.
In other words, users take whatever state they need, and unrelated states don't trigger re-rendering. This way, a component that originally needed to render 4~5 times now might only need to render 1~2 times. This represents a significant performance improvement.
Due to the immense amount of work involved, we have only optimized the dependencies collection for some Hooks for now, planning to gradually optimize other Hooks in the future.
The underlying principle of implementation is actually quite simple. It only requires maintaining a ref
internally and marking the state as "used" through the getter
function when exposing return values. When a user uses a state, this state is marked as "used", and during changes, it is determined whether re-rendering is needed.
Below is a simple pseudocode to demonstrate the underlying principle of dependency collection:
Through such methods, we can implement a simple dependency collection system, where re-rendering is only triggered when the user uses a particular state. Within @shined/react-use
, this entire set of logic has been integrated into the useTrackedRefState()
Hook (not yet publicly exposed), to implement the dependencies collection feature.