Skip to main content

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:

Interactive Demo: Use the Storybook controls at the top to customize this component.Open in New Tab →

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:

Interactive Demo: Use the Storybook controls at the top to customize this component.Open in New Tab →

Implementation:

const [variant, setVariant] = useState<'a' | 'b'>('a');

return (
<SafeSpan dataSource={`cta.variant-${variant}`} />
);

📄 Rich Media Content

Handle complex HTML content with automatic transformation:

Interactive Demo: Use the Storybook controls at the top to customize this component.Open in New Tab →

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:

Interactive Demo: Use the Storybook controls at the top to customize this component.Open in New Tab →

Security Features:

  • Script Removal - All <script> tags automatically removed
  • Attribute Filtering - Dangerous attributes like onerror stripped
  • Safe Elements - Only whitelisted HTML elements allowed
  • XSS Protection - Built-in protection against cross-site scripting

⚡ Performance Optimization

Built-in caching and performance features:

Interactive Demo: Use the Storybook controls at the top to customize this component.Open in New Tab →

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:

Interactive Demo: Use the Storybook controls at the top to customize this component.Open in New Tab →

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:

Interactive Demo: Use the Storybook controls at the top to customize this component.Open in New Tab →

Error Handling Strategy:

  1. Fallback Props - Use provided props when data source fails
  2. Placeholder Text - Show placeholder when content is empty
  3. Custom Fallbacks - Specify custom fallback options
  4. 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