React Use Current โ€” A Tiny React Hook for Synchronous Reactive State

#react#reacthooks#reactivejs#reactivity#vref#javascript#webdevelopment#opensource#frontenddev

๐Ÿš€ React Use Current โ€” Reactive + Synchronous State in React

React gives us two main primitives for storing state:

โŒ useState

โŒ useRef

โœ”๏ธ useCurrent (built on VRef)

This hook gives React something it never had out-of-the-box:

Direct mutation that triggers re-renders โ€” immediately and safely.


๐Ÿ” What Is React Use Current?

react-use-current is a tiny hook built on top of VRef (vref).
It gives React the ability to:

No need for setState(), shallow copying, or immutable patterns.

npm install react-use-current

๐Ÿงช Quick Example

import useCurrent from "react-use-current"; export default function Counter() { const count = useCurrent(0); return ( <button onClick={() => (count.value += 1)}> Count: {count.value} </button> ); }

โœ” updates instantly
โœ” mutates directly
โœ” re-renders correctly


๐Ÿง  Why Does This Hook Exist?

React developers often hit these problems:

โŒ "I need immediate state updates"

useState doesn't update until next render.
useCurrent updates instantly.

โŒ "I want to mutate state directly (nested objects)"

useState forces immutability โ†’ slow & annoying.
useCurrent allows:

user.address.city = "Phnom Penh";

โŒ "useRef doesn't re-render when changed"

ref.current++ won't update UI.
useCurrent will.


๐Ÿ”Ž Comparison Table

FeatureuseStateuseRefuseCurrent
Reactiveโœ”๏ธโŒโœ”๏ธ
SynchronousโŒโœ”๏ธโœ”๏ธ
Deep mutationโŒโœ”๏ธโœ”๏ธ
Triggers re-renderโœ”๏ธโŒโœ”๏ธ
Requires immutable updatesโœ”๏ธโŒโŒ
Built on VRefโŒโŒโœ”๏ธ

๐Ÿ— How It Works (In Short)


๐Ÿงฉ Real Example โ€” Objects, Deep Mutation, and Tracking

import { useEffect, useMemo } from "react"; import useCurrent, { track } from "react-use-current"; export default function UserCard() { const { value: user } = useCurrent({ name: "John", age: 25, }); // Run whenever user changes (deep) useEffect(() => { console.log("User mutated:", user); }, [track(user)]); // Memo recomputes when specific field changes const isAdult = useMemo(() => user.age >= 18, [track(user.age)]); // track for primitive is optional return ( <div> <p>{user.name} โ€” {user.age}</p> <button onClick={() => (user.age += 1)}>Increase Age</button> <button onClick={() => (user.name = "Doe")}> Change Name </button> </div> ); }

๐Ÿ”ง Auto-Tracking Helpers

These come from react-use-current (optional but powerful)


๐ŸŸฆ useApply

A version of useEffect that auto-tracks dependencies.

import { useApply } from "react-use-current"; useApply(() => { console.log("User changed:", user); }, [user]);

Equivalent to:

useEffect(() => {}, [track(user)]);

๐ŸŸง useCompute

A version of useMemo that auto-tracks dependencies.

import { useCompute } from "react-use-current"; const isAdult = useCompute(() => { return user.age >= 18; }, [user.age]);

Equivalent to:

useMemo(() => ..., [track(user.age)]);

๐Ÿงฌ Understanding the track() Function

track() converts reactive values into new value that React can detect in dependency arrays.

const updatedAt = track(user); // reactive object

Tracking is required for:

This mechanism is identical to VRef's change reporters โ€” but adapted for React.


๐Ÿ“ฆ Real Use Cases

โœ” Complex forms

Directly mutate nested form fields without cloning.

โœ” Synchronous logic (counters, timers, scrolling)

Get immediate updatesโ€”no batching.

โœ” Local reactive stores

Like lightweight MobX-style state.

โœ” Avoid expensive cloning in large objects

Mutate in place, but still reactive.


๐ŸŽฎ Live Playground

Play with react-use-current:
๐Ÿ‘‰ Open Live Playground


๐Ÿ“ฆ Try It

๐ŸŸข npm: https://www.npmjs.com/package/react-use-current
๐Ÿ™ GitHub: https://github.com/JohnSoatra/react-use-current

Reference:
๐ŸŒ Docs: https://doc.soatra.com/vref (VRef base)


๐Ÿ’ฌ What do you think?
What do you think?
Would this help in forms, real-time state, animations, or nested data?


๐Ÿ“ฌ Contact me ๐Ÿ‘‰ LinkedIn โ€“ John Soatra