The useKlint Pattern
The useKlint hook is the foundation of every Klint sketch. Understanding this pattern is crucial for building with Klint.
Basic Pattern
Every Klint sketch follows this pattern:
import { useKlint, Klint } from '@shopify/klint';
function MySketch() {
const { context } = useKlint();
const draw = (K) => {
// Your drawing code here
};
return (
<div style={{ width: '100vw', height: '100vh' }}>
<Klint context={context} draw={draw} />
</div>
);
}
Klint fills its container — always wrap it in a div with explicit dimensions.
What useKlint Provides
The useKlint hook returns several utilities:
const {
context, // Canvas context (required for Klint component)
KlintMouse, // Mouse tracking hook
KlintKeyboard, // Keyboard tracking hook
KlintImage, // Image loading hook
KlintWindow, // Window events hook
KlintScroll, // Scroll handling hook
KlintGesture, // Touch gesture hook
KlintTimeline, // Animation timeline hook
KlintPerformance, // Performance monitoring hook
useDev, // Development utilities
togglePlay, // Play/pause control
} = useKlint();
Each of these is documented in detail in Klint Hooks.
The Context Object
The context is a wrapped canvas context that must be passed to the <Klint> component:
const { context } = useKlint();
return <Klint context={context} draw={draw} />;
This pattern ensures:
- Canvas is properly initialized
- Drawing functions have access to the enhanced context
- Performance optimizations are applied
- No unnecessary React re-renders
Mouse Tracking
Use KlintMouse to track mouse position and state:
function MouseSketch() {
const { context, KlintMouse } = useKlint();
const { mouse } = KlintMouse();
const draw = (K) => {
K.background('#000');
K.fillColor(mouse.isPressed ? 'red' : 'white');
K.circle(mouse.x, mouse.y, 30);
};
return (
<div style={{ width: '100vw', height: '100vh' }}>
<Klint context={context} draw={draw} />
</div>
);
}
The mouse object provides x, y, px, py (previous position), vx, vy (velocity), isPressed, isHover, and angle. See KlintMouse for the full API.
State Without Re-renders
The useStorage hook provides state that doesn't trigger React re-renders. It uses get(key) and set(key, value) methods:
import { useKlint, Klint, useStorage } from '@shopify/klint';
function ParticleSketch() {
const { context } = useKlint();
const storage = useStorage({
particles: [],
count: 0
});
const setup = (K) => {
const pts = Array(100).fill(null).map(() => ({
x: Math.random() * K.width,
y: Math.random() * K.height,
vx: Math.random() * 2 - 1,
vy: Math.random() * 2 - 1
}));
storage.set('particles', pts);
};
const draw = (K) => {
K.background('#000');
const particles = storage.get('particles');
for (const p of particles) {
p.x += p.vx;
p.y += p.vy;
K.fillColor('white');
K.circle(p.x, p.y, 2);
}
storage.set('count', storage.get('count') + 1);
};
return (
<div style={{ width: '100vw', height: '100vh' }}>
<Klint context={context} setup={setup} draw={draw} />
</div>
);
}
Key Takeaways
- Always use
useKlint()— It's the entry point to all Klint functionality - Pass
contextto<Klint>— This connects your functions to the canvas - Wrap in a sized container — Klint fills its parent element
- Use provided hooks — KlintMouse, KlintKeyboard, etc. for interactivity
- Prefer
useStorage— For state that changes frequently without needing React re-renders - Functions run outside React — Your draw/setup functions execute in a separate animation loop
Next Steps
- TypeScript Setup — Type-safe Klint development
- Lifecycle Functions — Understanding setup, draw, and preload
- Klint Hooks — Full hook API reference
- React Integration — Advanced React patterns