Skip to main content

Components

Components are the building blocks of Refract applications. They're pure and reusable functions that take a lens and return JSX, similar to React components but with built-in reactivity. They allow you to break UI into independent and organized pieces that can be easy referencing.

Creating components​

Refract components are create using createComponent. This allows you to make use of the component anywhere in the app without adding export identifier at the end of the function.

Here is a typical example of form component:

//with export identifier
import React, { useState } from "react";

export const Form = () => {
const [name, setName] = useState("World");

return (
<div>
<h1>Hello, {name}!</h1>
<input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Enter your name"
/>
</div>
);
};

Component Props​

Refract components can receive props just like React components by using lens. Props are pieces of data passed from a parent to a child component, following a specific rule that allows the data to be modified. They're useful when a component needs to work with a defined set of data rules.

For example:

app.jsx
const App = createComponent(({ lens }) => {
const user = lens.useRefraction({ name: "Alice", age: 25 });

return (
<div>
<UserProfile
user={user.value}
onUpdate={(updates) => user.set({ ...user.value, ...updates })}
/>
</div>
);
});

From this example, Parent component owns the data and track of the user object. While the child display it and ask the parent to update it without breaking the data rule. So if you add another variable to the props, you get an error message.

Component lifecycle​

You can manage a component lifestyle through lens in term of starts, updates, or stops e.g Timer watch:

timer.jsx
const Timer = createComponent(({ lens }) => {
const seconds = lens.useRefraction(0);
const isRunning = lens.useRefraction(false);

// Effect runs when component mounts and when dependencies change
lens.useEffect(() => {
if (!isRunning.value) return;

const interval = setInterval(() => {
seconds.set((s) => s + 1);
}, 1000);

// Cleanup function runs when effect re-runs or component unmounts
return () => clearInterval(interval);
}, [isRunning.value]);

return (
<div>
<h2>Timer: {seconds.value}s</h2>
<button onClick={() => isRunning.set(!isRunning.value)}>
{isRunning.value ? "Stop" : "Start"}
</button>
<button onClick={() => seconds.set(0)}>Reset</button>
</div>
);
});