Skip to main content

Components

Building with Components

Components are the building blocks of Refract apps. Think of them like LEGO pieces—each one encapsulates a piece of UI, its behavior, and its connection to state. But unlike other frameworks, Refract components are reactive by default and optically aware.

import { createComponent } from 'refract';

const Greeting = createComponent(({ lens }) => {
const name = lens.useRefraction('World');
return <h1>Hello, {name}!</h1>;
});

↑ The simplest Refract component (see Quick Start.

Why Refract Components?

1. Automatic Reactivity

No need for useState or useEffect—just use refractions and everything stays in sync:

const Counter = createComponent(({ lens }) => {
const count = lens.useRefraction(0); // Auto-updates UI when changed
return <button onClick={() => count.set(count.value + 1)}>{count.value}</button>;
});

2. Optical Composition

Seamlessly plug in optics (reusable state logic):

const UserCard = createComponent(({ lens }) => {
const user = lens.useOptic(useUserProfile); // Reusable optic
return <div>{user.name}</div>;
});

🔗 Learn more: Optics Guide

3. Scoped Effects

Side effects are contained within components using lenses:

lens.useEffect(() => {
fetchData().then(updateUI);
}, []);

No more dependency array guesswork—Refract tracks them automatically.

Component Anatomy

Here’s what makes a Refract component unique:

PartPurposeExample
lensGateway to state/effectslens.useRefraction()
OpticsReusable state logiclens.useOptic(useMousePosition)
JSXDeclarative UI (like React)<div>{value}</div>
tip

Keep components small and pair them with optics for complex logic. Need a pattern? See Optical Composition Patterns.

Creating Components

Basic Component

const Button = createComponent(({ lens }) => {
const clicks = lens.useRefraction(0);
return (
<button onClick={() => clicks.set(clicks.value + 1)}>
Clicked {clicks.value} times
</button>
);
});

Composed Component

// Uses an optic for mouse tracking
const MouseTracker = createComponent(({ lens }) => {
const { x, y } = lens.useOptic(useMousePosition);
return <div>Mouse at: {x}, {y}</div>;
});

🔗 Try this in Mouse Tracker Tutorial

Performance Tips

caution

Avoid these common pitfalls:

// ❌ Don’t create refractions in render (use optics instead)
const unstable = createComponent(() => {
const temp = useRefraction(0); // Recreated on every render
});

// ❌ Don’t forget lens for effects
createComponent(() => {
useEffect(() => {}); // ❌ Won’t auto-cleanup! Use lens.useEffect
});

For optimization strategies:
➡️ Performance Guide

Next Steps