Conditional Rendering & Updating
What are they?
React Signify gives you two powerful tools to control when your state updates and when your components re-render:
conditionUpdating
: Decides when to accept new valuesconditionRendering
: Decides when to re-render components
Think of them as "gatekeepers" that prevent unnecessary work and improve performance.
// Only update when condition is met
signify.conditionUpdating((prevValue, newValue) => boolean);
// Only re-render when condition is met
signify.conditionRendering((currentValue) => boolean);
How the Flow Works
Here's what happens when you call .set()
:
1. Call .set(newValue)
2. → Check conditionUpdating(oldValue, newValue)
3. → If true: Update the value
4. → Check conditionRendering(currentValue)
5. → If true: Re-render components
Key insight: Both conditions must return true
for a complete update + re-render cycle.
conditionUpdating
- Control When Values Change
What it does
Controls whether a new value should be accepted into your state.
const sCounter = signify(0);
// Only allow positive numbers
sCounter.conditionUpdating((oldValue, newValue) => newValue >= 0);
sCounter.set(5); // ✅ Works: 0 → 5
sCounter.set(-1); // ❌ Blocked, stays 5
sCounter.set(10); // ✅ Works: 5 → 10
Common Use Cases
1. Validation
const sUserAge = signify(0);
sUserAge.conditionUpdating((prev, curr) => curr >= 18 && curr <= 120);
2. Only Allow Increases
const sScore = signify(0);
sScore.conditionUpdating((prev, curr) => curr >= prev);
3. Limit Array Size
const items = signify<string[]>([]);
items.conditionUpdating((prev, curr) => curr.length <= 100);
4. Prevent Too Frequent Updates
let lastUpdate = 0;
const sData = signify("");
sData.conditionUpdating(() => {
const now = Date.now();
const canUpdate = now - lastUpdate > 500; // 500ms gap
if (canUpdate) lastUpdate = now;
return canUpdate;
});
conditionRendering
- Control When Components Re-render
What it does
Controls whether components should re-render when the state changes.
const sCounter = signify(0);
// Only re-render on even numbers
sCounter.conditionRendering((value) => value % 2 === 0);
function Counter() {
const count = sCounter.use();
return <div>Count: {count}</div>;
}
sCounter.set(1); // ❌ No re-render (1 is odd)
sCounter.set(2); // ✅ Re-renders (2 is even)
sCounter.set(3); // ❌ No re-render (3 is odd)
Common Use Cases
1. Skip Loading States
const status = signify<"loading" | "success" | "error">("loading");
status.conditionRendering((value) => value !== "loading");
2. Only Show Important Notifications
const notifications = signify<Array<{ type: string }>>([]);
notifications.conditionRendering((items) =>
items.some((item) => item.type === "urgent")
);
3. Performance - Skip Empty States
const searchResults = signify<string[]>([]);
searchResults.conditionRendering((results) => results.length > 0);
4. Time-based Rendering
const sLivePrice = signify(100);
sLivePrice.conditionRendering(() => {
const hour = new Date().getHours();
return hour >= 9 && hour <= 17; // Only during business hours
});
Using Both Together
You can combine both conditions for maximum control:
const sUserProfile = signify({ name: "", email: "", isValid: false });
// Control updates: Only accept valid data
sUserProfile.conditionUpdating((prev, curr) => {
return curr.email.includes("@") && curr.name.length > 0;
});
// Control rendering: Only show when profile is complete
sUserProfile.conditionRendering((profile) => {
return profile.isValid;
});
function ProfileComponent() {
const profile = sUserProfile.use();
return <div>Welcome, {profile.name}!</div>;
}
// This will update but not render (email invalid)
sUserProfile.set({ name: "John", email: "invalid", isValid: true }); // ❌ Blocked by conditionUpdating
// This will update and render
sUserProfile.set({ name: "John", email: "john@email.com", isValid: true }); // ✅ Both conditions pass
Real-world Example: Shopping Cart
const sCart = signify({ items: [], total: 0 });
// Only accept valid cart updates
sCart.conditionUpdating((prev, curr) => {
const calculatedTotal = curr.items.reduce((sum, item) => sum + item.price, 0);
return Math.abs(calculatedTotal - curr.total) < 0.01; // Total must match
});
// Only render when cart has items
sCart.conditionRendering((cart) => cart.items.length > 0);
function Cart() {
const { items, total } = sCart.use();
return (
<div>
Cart: {items.length} items, ${total}
</div>
);
}
Quick Reference
Common Patterns
Form Validation
const sForm = signify({ email: "", password: "" });
sForm.conditionUpdating(
(prev, curr) => curr.email.includes("@") && curr.password.length >= 8
);
Real-time Data (rate limiting)
const sLiveData = signify(0);
sLiveData.conditionUpdating(
(prev, curr) => Math.abs(curr - prev) > 0.01 // Only update if change > 1%
);
Skip Loading States
const status = signify<"loading" | "ready">("loading");
status.conditionRendering((value) => value === "ready");
Game Score (no decreases)
const score = signify(0);
score.conditionUpdating((prev, curr) => curr >= prev);
Best Practices
✅ Do
- Keep condition functions simple and fast
- Use for validation and performance optimization
- Document why you're using each condition
❌ Don't
- Use expensive operations in conditions
- Make async calls in condition functions
- Over-engineer simple use cases
// ✅ Good: Simple and fast
counter.conditionUpdating((prev, curr) => curr >= 0);
// ❌ Avoid: Complex and slow
data.conditionUpdating((prev, curr) => {
return expensiveCalculation(curr) && networkCall(curr); // Too complex!
});
When to Use
Use conditionUpdating
when:
- Validating input data
- Preventing invalid state changes
- Rate limiting updates
Use conditionRendering
when:
- Skipping unnecessary re-renders
- Hiding components during loading
- Performance optimization
Use both when:
- You need full control over both state and UI updates
- Building complex forms or real-time applications
💡 Remember: These are optimization tools. Start simple, then add conditions when you need them!