Skip to main content

Common Issues

Find solutions to frequently encountered problems when working with Refract.

Component Not Updating When State Changes​

Problem: Your component doesn't re-render when you expect it to after changing state.

Solutions:

Make sure you're using lens.useRefraction() to create reactive state:

Correct State Creation
const MyComponent = createComponent(({ lens }) => {
// ✅ Correct - creates reactive state
const count = lens.useRefraction(0);

return (
<div>
<p>Count: {count.value}</p>
<button onClick={() => count.set(count.value + 1)}>
Increment
</button>
</div>
);
});

Side Effects Running Too Often​

Problem: Your useEffect() callbacks are running more frequently than expected.

Solutions:

Review your dependency arrays in useEffect() calls:

Proper Dependencies
const MyComponent = createComponent(({ lens, userId }) => {
const user = lens.useRefraction(null);

lens.useEffect(() => {
fetchUser(userId).then(user.set);
}, [userId]); // Only re-run when userId changes

// ❌ Wrong - runs on every render
// lens.useEffect(() => {
// fetchUser(userId).then(user.set);
// }); // Missing dependency array

return <div>User: {user.value?.name}</div>;
});

Performance Issues​

Problem: Your application feels slow or unresponsive.

Solutions:

Use Computed Values​

Use useComputed() for expensive calculations that depend on reactive state:

Optimizing Expensive Calculations

Using computed values to avoid unnecessary recalculations:

const ProductList = createComponent(({ lens, products }) => {
const searchQuery = lens.useRefraction("");
const sortBy = lens.useRefraction("name");

// ✅ Good - computed value caches expensive operations
const filteredProducts = lens.useComputed(() => {
return products
.filter(p => p.name.toLowerCase().includes(searchQuery.value.toLowerCase()))
.sort((a, b) => a[sortBy.value].localeCompare(b[sortBy.value]));
}, [products, searchQuery.value, sortBy.value]);

return (
<div>
<input
value={searchQuery.value}
onChange={(e) => searchQuery.set(e.target.value)}
/>
{filteredProducts.value.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
});

Break Down Large Components​

Consider breaking large components into smaller ones:

Component Decomposition

Breaking large components into smaller, focused pieces:

// ❌ Large monolithic component
const Dashboard = createComponent(({ lens }) => {
const user = lens.useRefraction(null);
const notifications = lens.useRefraction([]);
const settings = lens.useRefraction({});
const analytics = lens.useRefraction(null);

// Lots of logic and JSX...
return (
<div>
{/*Hundreds of lines of JSX*/}
</div>
);
});

// ✅ Broken down into focused components
const UserProfile = createComponent(({ lens, user }) => {
return <div>User profile content</div>;
});

const NotificationPanel = createComponent(({ lens, notifications }) => {
return <div>Notifications content</div>;
});

const Dashboard = createComponent(({ lens }) => {
const user = lens.useRefraction(null);
const notifications = lens.useRefraction([]);

return (
<div>
<UserProfile user={user.value} />
<NotificationPanel notifications={notifications.value} />
</div>
);
});

Build and Development Issues​

TypeScript Errors​

Common TypeScript integration problems:

Proper Type Definitions
// ✅ Good - explicit types
interface User {
id: number;
name: string;
email: string;
}

const UserComponent = createComponent(({ lens }: { lens: Lens }) => {
const user = lens.useRefraction<User | null>(null);

return <div>{user.value?.name}</div>;
});

Getting Help​

If you're still experiencing issues:

  • Documentation: Browse the complete docs for detailed guides
  • GitHub Issues: Report bugs or request features at github.com/refract-js/refract
  • Discord Community: Join the community for help and discussions
  • Stack Overflow: Tag questions with refract-js