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:
- Use useRefraction()
- Use .set() Method
Make sure you're using lens.useRefraction() to create reactive state:
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>
);
});
Check that you're calling .set() to update the state, not mutating directly:
const MyComponent = createComponent(({ lens }) => {
const items = lens.useRefraction([]);
const addItem = (newItem) => {
// ✅ Correct - creates new array
items.set([...items.value, newItem]);
// ❌ Wrong - mutates existing array
// items.value.push(newItem);
// items.set(items.value);
};
return <div>Items: {items.value.length}</div>;
});
Side Effects Running Too Often
Problem: Your useEffect() callbacks are running more frequently than expected.
Solutions:
- Review Dependencies
- Use Optics
Review your dependency arrays in useEffect() calls:
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>;
});
Consider using useOptic() for more complex effect management:
const useUserData = createOptic((lens, userId) => {
const user = lens.useRefraction(null);
const loading = lens.useRefraction(false);
lens.useEffect(() => {
if (!userId) return;
loading.set(true);
fetchUser(userId)
.then(user.set)
.finally(() => loading.set(false));
}, [userId]);
return { user: user.value, loading: loading.value };
});
const MyComponent = createComponent(({ lens, userId }) => {
const userData = lens.useOptic(useUserData, userId);
return <div>User: {userData.user?.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:
- Missing Types
- Generic Components
// ✅ 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>;
});
interface ListProps<T> {
lens: Lens;
items: T[];
renderItem: (item: T) => JSX.Element;
}
const List = <T,>({ lens, items, renderItem }: ListProps<T>) => {
const selectedItem = lens.useRefraction<T | null>(null);
return (
<div>
{items.map((item, index) => (
<div key={index} onClick={() => selectedItem.set(item)}>
{renderItem(item)}
</div>
))}
</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
Related Resources
- State Management Best Practices - Effective state patterns
- Effects Best Practices - Managing side effects
- Performance Optimization - Advanced performance techniques