Unique Instances
By default, navigating to another page or hiding a component with If() destroys the component. Rendering it again creates a new instance.
Recreation resets internal state in interactive elements. For example, a playing video stops, a canvas drawing is lost, and form inputs reset.
Unique instances preserve a component while it moves within the application.
Creating Persistent Components
Wrap a component function in createUnique() to preserve its instance:
import { createUnique } from 'retend'; export const PersistentVideo = createUnique(() => { return ( <video src="https://example.com/video.mp4" controls autoplay> Your browser does not support the video tag. </video> ); });
If <PersistentVideo /> is rendered on the Home page and then on the About page, Retend moves the same component instance to the new location. The video retains its playback state.
Multiple Independent Instances
By default, uses of a unique component share one underlying instance. If <PersistentVideo /> is rendered in two places at the same time, the instance moves to the last rendered location.
To create independent instances that can coexist, give each use a unique id prop:
// Two separate video players, each with their own state <PersistentVideo id="camera-1" /> <PersistentVideo id="camera-2" />
camera-1 and camera-2 are independent persistent instances.
Passing Props
Props for a unique component are provided to its function as one reactive Cell. The component can react when it moves to a location with different props.
import { createUnique, Cell } from 'retend'; const UniquePanel = createUnique((props) => { // 1. Create a derived Cell so the title automatically updates const title = Cell.derived(() => props.get().title); return ( <div class="panel"> <h2>{title}</h2> <p>This panel persists as it moves.</p> </div> ); }); // If rendered here... <UniquePanel id="panel-1" title="First Title" /> // And then later moved here... <UniquePanel id="panel-1" title="Updated Title" /> // The exact same component instance is used, but the <h2> text updates instantly!
Saving and Restoring Scroll Position
createUnique preserves the component instance, but some DOM state, such as scroll position, resets when the component moves between locations.
Use the onMove hook to save and restore that state:
import { createUnique, onMove, Cell } from 'retend'; const ScrollableArea = createUnique(() => { const ref = Cell.source<HTMLDivElement | null>(null); onMove(() => { const element = ref.get(); if (!element) return; const scrollPos = element.scrollTop; return () => { element.scrollTop = scrollPos; }; }); return ( <div ref={ref} style={{ height: '400px', overflow: 'auto' }}> <p>Lots of content here...</p> </div> ); });
The onMove hook runs before the unique component moves. Return a function from the hook to run after the move completes.
Use unique instances when a component must retain internal state across navigation.