๐ญ React Latest Ref Pattern
I wasnโt a fan of React until it introduced hooks, especially useEffect()
, which makes lifecycle management much cleaner compared to all other client-side platforms Iโve worked with, as the initialization code and its cleanup code are colocated.
The Problem
However, the APIโs cleanliness comes with a cost. The dependency array is confusing and error-prone. If something is missed, the effect may not get triggered when it should, or it may use stale values in the effect closure.
The React team turned to linters and created the โreact-hooks/exhaustive-depsโ ESLint rule, which brings its own problem of triggering effects more than necessary. I wish the useEffect()
API was designed with separate parameters for:
- Triggering the effect (the dependency array)
- Updating the values used inside the effect (another parameter)
The Solution
So I started to use the dependency array only to trigger the effect and used the useRef()
hook to get the latest value inside the effect.
I learned from Epic React by Kent C. Dodds that this is called the Latest Ref pattern.
And I implemented the API I wished for:
Example
Here is a simple example, which validates the userโs input asynchronously, with a mock check that returns true
if the length of the value is an odd number, in a random duration between 200ms and 1s.
It only triggers the async validation when the input value changes, so we only want value
in the dependency array.
Once the result comes back, we want to use the latest values in the callback.
There are other ways to achieve this and some may be simpler. Below is just to showcase the usage of useLatestRefEffect()
, which separates the concerns to re-trigger the effect, and keep the values used inside the effect up to date.