Data Binding System
The QwickApps React Framework data binding system enables dynamic content management by connecting components to external data sources like CMS systems, APIs, or JSON data. This powerful feature allows you to build applications where content can be updated without code changes.
Core Concepts
Data Sources
Data sources are string identifiers that point to specific content in your data provider. They use dot notation to navigate nested data structures:
// Examples of data source paths
"company.description" // Basic company info
"pages.home.hero-block" // Page-specific content
"content.en.welcome" // Multi-language content
"blog.featured-post" // Dynamic blog content
useDataBinding Hook
The core hook that resolves component props from data sources:
import { useDataBinding } from '@qwickapps/react-framework';
const { loading, error, $dataSource, $cached } = useDataBinding<MyModel>(
dataSource, // Data source identifier
fallbackProps, // Props when data unavailable
schema, // Component schema for validation
options // Binding configuration
);
Automatic Integration
All Framework components support data binding through the dataSource prop:
// Traditional props
<Button label="Click Me" variant="primary" />
// Data binding
<Button dataSource="buttons.cta" />
Key Features
🌍 Multi-language Support
Dynamically switch content languages using data source paths:
Implementation:
const [language, setLanguage] = useState<'en' | 'es'>('en');
return (
<SafeSpan dataSource={`content.${language}.welcome`} />
);
Data Structure:
{
"content.en.welcome": [{
"html": "<h2>Welcome to QwickApps</h2><p>The future of app development is here.</p>"
}],
"content.es.welcome": [{
"html": "<h2>Bienvenidos a QwickApps</h2><p>El futuro del desarrollo está aquí.</p>"
}]
}
🧪 A/B Testing
Test different content variants to optimize conversions:
Implementation:
const [variant, setVariant] = useState<'a' | 'b'>('a');
return (
<SafeSpan dataSource={`cta.variant-${variant}`} />
);
📄 Rich Media Content
Handle complex HTML content with automatic transformation:
Features:
- HTML to React - Automatic conversion of HTML strings to React components
- Content Sanitization - Built-in XSS protection and safe rendering
- Framework Integration - HTML elements transformed to Framework components
- Media Support - Images, links, and rich formatting preserved
🛡️ Security & Sanitization
Automatic protection against malicious content:
Security Features:
- Script Removal - All
<script>tags automatically removed - Attribute Filtering - Dangerous attributes like
onerrorstripped - Safe Elements - Only whitelisted HTML elements allowed
- XSS Protection - Built-in protection against cross-site scripting
⚡ Performance Optimization
Built-in caching and performance features:
Performance Features:
- Memory Caching - Configurable TTL and cache size limits
- Cache Hit Monitoring - Track cache performance and hit ratios
- Automatic Invalidation - Smart cache updates when data changes
- Efficient Re-rendering - Minimized updates using React optimization
🔧 Custom Hook Usage
Direct hook usage for advanced scenarios:
Implementation:
const CustomComponent = ({ dataSource }) => {
const { loading, error, data } = useDataBinding(
dataSource,
fallbackProps,
schema,
{ strict: true, cache: true }
);
if (loading) return <LoadingComponent />;
if (error) return <ErrorComponent error={error} />;
return <SafeSpan dataSource={dataSource} />;
};
❌ Error Handling
Graceful degradation when data is unavailable:
Error Handling Strategy:
- Fallback Props - Use provided props when data source fails
- Placeholder Text - Show placeholder when content is empty
- Custom Fallbacks - Specify custom fallback options
- Never Break UI - Always render something useful
Data Providers
JsonDataProvider
For static JSON data or mock data during development:
import { JsonDataProvider } from '@qwickapps/schema';
const jsonProvider = new JsonDataProvider({
data: {
'company.name': [{ html: 'QwickApps' }],
'company.description': [{ html: 'Revolutionary app development platform' }]
}
});
CachedDataProvider
Wrapper that adds caching to any data provider:
import { CachedDataProvider } from '@qwickapps/schema';
const cachedProvider = new CachedDataProvider(jsonProvider, {
maxSize: 100, // Maximum cache entries
defaultTTL: 60000 // 1 minute cache TTL
});
Custom Data Providers
Implement the DataProvider interface for custom data sources:
class CMSDataProvider implements DataProvider {
async getData(path: string): Promise<any[]> {
// Fetch from your CMS API
const response = await fetch(`/api/cms/${path}`);
return response.json();
}
}
Configuration
DataProvider Setup
Configure your data provider at the app root:
import { DataProvider } from '@qwickapps/react-framework';
function App() {
return (
<DataProvider dataSource={{ dataProvider: cachedProvider }}>
<YourApp />
</DataProvider>
);
}
Binding Options
Customize data binding behavior:
<Button
dataSource="buttons.cta"
bindingOptions={{
cache: true, // Enable caching
strict: false, // Flexible validation
cacheTTL: 300000, // 5 minute cache
fallback: { // Custom fallback
label: 'Default Button',
variant: 'primary'
}
}}
/>
Best Practices
1. Consistent Naming
Use clear, hierarchical naming for data sources:
✅ Good:
- pages.home.hero-title
- components.footer.copyright
- content.en.navigation.about
❌ Avoid:
- title1
- some_data
- temp_content
2. Fallback Strategy
Always provide meaningful fallbacks:
// Provide sensible fallbacks
<Button
dataSource="buttons.cta"
label="Get Started" // Fallback label
variant="primary" // Fallback variant
/>
3. Performance Optimization
Use caching for frequently accessed data:
// Enable caching for static content
<Article
dataSource="content.about-us"
bindingOptions={{ cache: true, cacheTTL: 600000 }}
/>
4. Error Boundaries
Wrap data-bound components in error boundaries:
<ErrorBoundary>
<Button dataSource="dynamic.button" />
</ErrorBoundary>
5. Loading States
Handle loading states appropriately:
const MyComponent = ({ dataSource }) => {
const { $loading } = useDataBinding(dataSource);
if ($loading) {
return <Skeleton variant="rectangular" />;
}
return <Button dataSource={dataSource} />;
};
Integration Examples
CMS Integration
Connect to headless CMS systems:
// Contentful integration
class ContentfulProvider implements DataProvider {
async getData(path: string) {
const entry = await contentfulClient.getEntry(path);
return [{
html: entry.fields.content,
title: entry.fields.title
}];
}
}
API Integration
Connect to REST APIs:
// REST API integration
class APIDataProvider implements DataProvider {
async getData(path: string) {
const response = await fetch(`/api/content/${path}`);
const data = await response.json();
return Array.isArray(data) ? data : [data];
}
}
Real-time Updates
Connect to real-time data sources:
// WebSocket integration
class RealtimeProvider implements DataProvider {
async getData(path: string) {
return new Promise((resolve) => {
const ws = new WebSocket(`ws://api.example.com/${path}`);
ws.onmessage = (event) => {
resolve(JSON.parse(event.data));
};
});
}
}
Advanced Features
Schema Validation
Use schema validation for type safety:
import ButtonModel from '@qwickapps/react-framework/schemas/ButtonSchema';
// Automatic validation against ButtonModel schema
<Button
dataSource="buttons.cta"
bindingOptions={{ strict: true }}
/>
Template Variables
Support for dynamic content with variables:
{
"user.greeting": [{
"html": "Hello <strong>{{userName}}</strong>, welcome back!",
"variables": { "userName": "John Doe" }
}]
}
Conditional Content
Show different content based on conditions:
const variant = user.isPremium ? 'premium' : 'free';
<Button dataSource={`cta.${variant}`} />
Learn More
- Component Overview - See which components support data binding
- Schema System - Learn about type-safe data validation
- Performance Guide - Optimize your data binding performance
- CMS Integration Guide - Connect to WordPress, Strapi, and other CMS platforms