Installation — @piplup/utils
Install @piplup/utils, check its React peer dependency, and see which helpers and hooks it exports and how they behave during server rendering.
@piplup/utils is a set of small functions and React hooks that other Piplup packages are built on: ref helpers, an event listener hook, and localStorage helpers that keep components in sync. You can use them directly in your own code.
npm install @piplup/utilsPeer dependencies
| Package | Version |
|---|---|
react | ^18.2.0 || ^19.0.0 |
@types/react (optional) | ^18.2.0 || ^19.0.0 |
If you use @piplup/rhf-core, this package is already installed: rhf-core depends on @piplup/utils 3.2.4 directly. @piplup/rhf-adapters lists the same version as a peer dependency.
Entry point
There is a single entry point, the package root. It ships ES module and CommonJS builds with TypeScript types, and is marked sideEffects: false, so bundlers drop the exports you don't import.
import {
// helpers
compact,
execSequentially,
forkRef,
hasOwnProperty,
setRef,
// localStorage helpers
getItem,
removeItem,
setItem,
// hooks
useEventCallback,
useEventListener,
useForkRef,
useIsomorphicEffect,
useLocalStorage,
} from "@piplup/utils";Server rendering
The bundle starts with a "use client" directive, so in the Next.js App Router the hooks must be called from Client Components. The exports are safe to import on the server:
getItemreturnsnullwhen there is nowindow, andsetItemandremoveItemdo nothing.useLocalStoragestarts from itsinitialValueon the server and reads the stored value after hydration.useIsomorphicEffectisuseLayoutEffectin the browser anduseEffecton the server.useEventListenerattaches its listener in an effect, so it never toucheswindowon the server.
Quick example
setItem notifies every useLocalStorage hook that reads the same key, in the current tab as well as in other tabs. Two components can share a value without a context:
"use client";
import { setItem, useLocalStorage } from "@piplup/utils";
function ThemeLabel() {
const theme = useLocalStorage("theme", "light");
return <span>Theme: {theme}</span>;
}
function ThemeToggle() {
const theme = useLocalStorage("theme", "light");
return (
<button onClick={() => setItem("theme", theme === "dark" ? "light" : "dark")}>
Toggle theme
</button>
);
}Writing with localStorage.setItem directly does not update hooks in the same tab, because the browser's storage event only fires in other tabs. Use the exported setItem and removeItem instead.