@ritojs/react is the React integration layer on top of the Web reader from
@ritojs/core/web and the controller layer from @ritojs/kit.
Use it when you want hooks for reader lifecycle and state, plus a mount component for the controller-managed reading surface.
import { useRitoReader, Reader } from '@ritojs/react';Hooks:
useRitoReaderuseSelectionuseSearchuseAnnotationsuseReadingPositionuseContainerSizeuseControllerEvent
Types:
UseRitoReaderOptionsRitoReaderStateRitoReaderActionsSelectionStateSearchStateAnnotationsStateReadingPositionStateContainerSize
Components:
ReaderReaderProps
import { useEffect, useRef } from 'react';
import { Reader, useContainerSize, useRitoReader } from '@ritojs/react';
export function App() {
const [containerRef, containerSize] = useContainerSize();
const width = Math.max(containerSize.width, 1);
const height = Math.max(containerSize.height, 1);
const didLoadRef = useRef(false);
const { controller, isLoaded, load, resize } = useRitoReader({
reader: {
width,
height,
margin: 40,
spread: 'double',
},
controller: {
transition: { stiffness: 180, damping: 22 },
},
});
useEffect(() => {
if (containerSize.width === 0 || containerSize.height === 0) return;
if (didLoadRef.current) return;
didLoadRef.current = true;
void load(fetch('/book.epub').then((resp) => resp.arrayBuffer()));
}, [containerSize.width, containerSize.height, load]);
useEffect(() => {
if (!isLoaded) return;
resize(width, height);
}, [height, isLoaded, resize, width]);
return (
<div ref={containerRef} style={{ width: '100vw', height: '100vh' }}>
<Reader controller={controller} />
</div>
);
}This is the highest-level React hook. It manages:
- canvas creation
createReader()createController()- state synchronization for spread count and active spread
- cleanup on unmount
Use this hook when you want a full reader lifecycle in React.
Important behavior:
- rendering the hook itself is SSR-safe
load()still needs a browser document and should run in an effect or event handlerload()is separate from later responsive resizes; callresize()when container size changes after load- sizing remains your responsibility; pair it with
useContainerSize()or your own layout observer
The Reader component mounts the controller's managed DOM surface into a container.
It does not own pagination logic itself, and it does not call controller.resize() for you.
The controller remains the source of truth.
- Use
@ritojs/reactif you want fast app integration and React state bindings. - Use
@ritojs/kitdirectly if you want non-React UI or a custom state layer. - Use
@ritojs/core/webif you only need browser Canvas rendering. - Use
@ritojs/coreif you only need platform-neutral parsing, pagination, and display-list primitives.