use Graft Reload
A flag that goes up and comes back down after a delay, to remount a subtree.
API
Options
| prop | type | default | |
|---|---|---|---|
delay? | number | 0 | milliseconds the flag stays up |
Returns
| prop | type | default | |
|---|---|---|---|
isReloading? | boolean | — | whether a reload is in progress |
onReload? | () => void | — | raises the flag |
id? | string | — | stable id |
Usage
Up, then down
// -constants/graft_panel.ts
export const GraftPanel = createGraft({ name: "GraftPanel", graft: useGraftReload });
// -components/reload_button.tsx
export const ReloadButton = () => {
const { isReloading, onReload } = GraftPanel.use();
return (
<Button disabled={isReloading} open={isReloading} onClick={onReload}>
<Button.IconLabel reverse icon={<Button.Icon icon={<Spinner />} />} label={<Button.Label label="reload" />} />
</Button>
);
};Details
Remounting on purpose
Sometimes the cheapest way to reset a subtree is to stop rendering it for a moment. Swap it out while isReloading is up and everything below goes with it — state, refs, effects, whatever an uncontrolled input was holding — and comes back the way it started.
// -components/panel_controls.tsx
export const PanelControls = () => {
const { isReloading, onReload } = GraftPanel.use();
return (
<>
<Button disabled={isReloading} open={isReloading} onClick={onReload}>
<Button.IconLabel reverse icon={<Button.Icon icon={<Spinner />} />} label={<Button.Label label="reload" />} />
</Button>
<Guard guardIf={isReloading} shouldHide>
<PanelBody />
</Guard>
</>
);
};
// -components/panel_body.tsx — everything in here is new after a reload
export const PanelBody = () => {
const [mountedAt] = useState(() => new Date().toLocaleTimeString());
const [clicks, setClicks] = useState(0);
return (
<>
<Button onClick={() => setClicks((previous) => previous + 1)}>{`clicks: ${clicks}`}</Button>
<Chip>{`mounted at ${mountedAt}`}</Chip>
</>
);
};A key does the same thing when you have something to key on. This is for the times you do not: nothing changed, you simply want it new again.
The delay is the point
With delay at zero the flag is up for a single frame — enough to remount, invisible to the eye. Give it a few hundred milliseconds instead and the same flag doubles as the condition for a skeleton, so the reset does not read as a flicker.
It measures nothing and waits for nothing: it is a timer, not a request. If what you are reloading is asynchronous, its own pending state is the one to render — this one just decides when the subtree is replaced.