Skip to Content
ChatSharing Context

Sharing React Context with AI

The useAIContext hook allows React components to share their state with the AI without causing re-renders. This enables the AI to provide personalized responses based on user data, app settings, and component state.

User Profile

App Settings

Current AI Context (0 items)

No context items currently shared

AI with Shared Context

AI knows your profile, settings, and session state

Ready to chat?

Send a message to get started

How Context Sharing Works

Context sharing creates a bridge between your React state and the AI model:

  1. No Re-renders: Context updates don’t trigger chat interface re-renders
  2. Automatic Updates: When state changes, context is automatically updated
  3. Structured Data: Context items include metadata for better AI understanding
  4. Priority System: Control which context is most important to the AI
  5. Lifecycle Management: Context is automatically cleaned up when components unmount

Basic Usage

The useAIContext hook accepts an options object:

import { useAIContext } from "ai-chat-bootstrap"; function UserProfile() { const [user, setUser] = useState({ name: "Alice Johnson", role: "admin", plan: "pro" }); // Share user profile with AI useAIContext({ description: "User Profile", value: user, priority: 100, }); return <div>...</div>; }

Examples

Priority System

Higher priority context items are sent first to the AI:

// High priority - critical user info useAIContext({ description: "User Auth", value: authData, priority: 100 }); // Medium priority - app state useAIContext({ description: "App Settings", value: settings, priority: 80 }); // Low priority - metadata useAIContext({ description: "Session Info", value: sessionData, priority: 60 });

Complete Implementation Example

Here’s a full example showing multiple context items:

"use client"; import React, { useState, useMemo } from "react"; import { ChatContainer, useAIChat, useAIContext } from "ai-chat-bootstrap"; export function AIContextDemo() { const [userProfile, setUserProfile] = useState({ userId: "user-123", name: "Alice Johnson", email: "alice@example.com", role: "admin", plan: "pro", notifications: true, }); const [settings, setSettings] = useState({ theme: "dark", language: "en", maxMessages: 100, autoSave: true, }); // Static session info const sessionInfo = useMemo(() => ({ sessionId: "session-" + Date.now(), startedAt: new Date().toISOString(), pageUrl: "/chat", userAgent: navigator.userAgent, }), []); // Share context with AI - updates automatically when state changes useAIContext({ description: "User Profile", value: userProfile, priority: 100, }); useAIContext({ description: "App Settings", value: settings, priority: 80, }); useAIContext({ description: "Session Info", value: sessionInfo, priority: 60, }); const chat = useAIChat({ api: "/api/chat", systemPrompt: "You are a helpful assistant with access to the user's profile, settings, and session information. Use this context to provide personalized responses." }); return ( <div className="space-y-4"> {/* User Profile Widget */} <div className="p-4 bg-card rounded-lg border"> <h3 className="text-lg font-semibold mb-3">User Profile</h3> <div className="space-y-2"> <input type="text" value={userProfile.name} onChange={(e) => setUserProfile(prev => ({...prev, name: e.target.value}))} className="w-full px-3 py-2 border rounded-md" placeholder="Name" /> <select value={userProfile.role} onChange={(e) => setUserProfile(prev => ({...prev, role: e.target.value}))} className="w-full px-3 py-2 border rounded-md" > <option value="user">User</option> <option value="admin">Admin</option> <option value="moderator">Moderator</option> </select> </div> </div> {/* Settings Widget */} <div className="p-4 bg-card rounded-lg border"> <h3 className="text-lg font-semibold mb-3">Settings</h3> <div className="space-y-2"> <select value={settings.theme} onChange={(e) => setSettings(prev => ({...prev, theme: e.target.value}))} className="w-full px-3 py-2 border rounded-md" > <option value="light">Light</option> <option value="dark">Dark</option> <option value="auto">Auto</option> </select> <select value={settings.language} onChange={(e) => setSettings(prev => ({...prev, language: e.target.value}))} className="w-full px-3 py-2 border rounded-md" > <option value="en">English</option> <option value="es">Spanish</option> <option value="fr">French</option> </select> </div> </div> {/* Chat Interface */} <ChatContainer chat={chat} header={{ title: "AI with Shared Context", subtitle: "AI knows your profile and settings", }} ui={{ placeholder: "Ask about your profile or settings!" }} /> </div> ); }

Backend Integration

The backend automatically receives context items in the request payload along with enrichedSystemPrompt (which already embeds Tools / Context / Focus summaries and appends your original systemPrompt if provided):

import { createAzure } from "@ai-sdk/azure"; import { convertToModelMessages, streamText } from "ai"; const azure = createAzure({ resourceName: process.env.AZURE_RESOURCE_NAME!, apiKey: process.env.AZURE_API_KEY!, apiVersion: process.env.AZURE_API_VERSION ?? "preview", }); const model = azure(process.env.AZURE_DEPLOYMENT_ID!); export async function POST(req: Request) { const { messages, enrichedSystemPrompt, tools } = await req.json(); const result = await streamText({ model, messages: [ { role: "system", content: enrichedSystemPrompt }, ...convertToModelMessages(messages), ], tools, }); return result.toUIMessageStreamResponse(); }

Note: Do NOT re-concatenate context data server-side. The client-built enrichedSystemPrompt already contains a standardized preamble plus conditional sections (Tools / Context / Focus) and then appends the original systemPrompt verbatim.

Advanced Usage Patterns

Dynamic Context Updates

Context automatically updates when your state changes:

function TaskManager() { const [currentTask, setCurrentTask] = useState(null); // Context updates automatically when task changes useAIContext({ description: "Active Task", value: currentTask ? { id: currentTask.id, title: currentTask.title, status: currentTask.status, dueDate: currentTask.dueDate, } : { message: "No active task" }, priority: 90, }); return <div>...</div>; }

Multiple Context Items from One Component

A single component can register multiple context items:

function Dashboard() { const [user, setUser] = useState(userData); const [projects, setProjects] = useState(projectsData); const [notifications, setNotifications] = useState(notificationsData); // User context useAIContext({ description: "User", value: user, priority: 100 }); // Projects context useAIContext({ description: "Projects", value: { activeProjects: projects.filter(p => p.status === 'active'), totalCount: projects.length, }, priority: 80, }); // Notifications context useAIContext({ description: "Notifications", value: { unreadCount: notifications.filter(n => !n.read).length, latestNotification: notifications[0], }, priority: 60, }); return <div>...</div>; }

Conditional Context

Only share context when certain conditions are met:

function ConditionalContext() { const [user, setUser] = useState(null); const [isAuthenticated, setIsAuthenticated] = useState(false); // Only share user context when authenticated useAIContext({ description: "User Authentication", value: isAuthenticated && user ? { id: user.id, name: user.name, permissions: user.permissions, } : { authenticated: false }, priority: 100, }); return <div>...</div>; }

API Reference

Best Practices

Preventing Re-render Loops

The useAIContext hook follows the critical Zustand pattern to prevent infinite re-renders:

// ✅ Correct - Only include stable values in dependencies useEffect(() => { setContextItem(contextData); return () => removeContextItem(id); // eslint-disable-next-line react-hooks/exhaustive-deps }, [id, data, opts?.label, opts?.description, opts?.scope, opts?.priority]); // ❌ Wrong - Including Zustand actions causes infinite loops }, [id, data, setContextItem, removeContextItem]); // Don't do this!

Data Structure

Keep context data serializable and structured:

// ✅ Good - Clean, serializable data useAIContext({ description: "User", value: { id: user.id, name: user.name, role: user.role, lastActive: user.lastActiveDate.toISOString(), }, }); // ❌ Avoid - Functions, DOM nodes, complex objects useAIContext({ description: "User", value: { ...user, onClick: handleClick, // Function - not serializable element: domRef.current, // DOM node - not serializable complexObject: someClass, // Complex object - may not serialize }});

Performance Optimization

Use useMemo for expensive context computations:

function ExpensiveContext() { const [rawData, setRawData] = useState([]); const processedContext = useMemo(() => ({ summary: rawData.reduce((acc, item) => acc + item.value, 0), categories: rawData.reduce((acc, item) => { acc[item.category] = (acc[item.category] || 0) + 1; return acc; }, {}), lastUpdated: new Date().toISOString(), }), [rawData]); useAIContext({ description: "Processed Data", value: processedContext, priority: 70 }); return <div>...</div>; }

Security Considerations

Never share sensitive data in context:

// ✅ Safe - Only share necessary, non-sensitive data useAIContext({ description: "User Profile", value: { displayName: user.displayName, role: user.role, preferences: user.preferences, }}); // ❌ Unsafe - Don't share sensitive information useAIContext({ description: "User Auth", value: { password: user.password, // Never share passwords apiKeys: user.apiKeys, // Never share API keys socialSecurity: user.ssn, // Never share PII creditCard: user.paymentInfo, // Never share payment info }});

Common Use Cases

User Profile Context

Share authenticated user information for personalized responses:

useAIContext({ description: "User Profile", value: userProfile, priority: 100 });

Application Settings

Share app configuration to tailor AI responses:

useAIContext({ description: "App Settings", value: appSettings, priority: 90 });

Current Page Context

Share information about the current page or view:

useAIContext({ description: "Page Context", value: { route: router.pathname, params: router.query, title: document.title, }, priority: 70 });

Form State

Share current form data for context-aware assistance:

useAIContext({ description: "Form State", value: { formType: "user-registration", completedFields: Object.keys(formData).filter(key => formData[key]), validationErrors: errors, }, priority: 80 });

Shopping Cart Context

Share e-commerce state for purchase assistance:

useAIContext({ description: "Shopping Cart", value: { items: cart.items, totalItems: cart.items.length, totalValue: cart.total, currency: "USD", }, priority: 85 });

How Context Flows

  1. Component Registration: Components call useAIContext() with state data
  2. Store Management: Context items are stored in a Zustand Map by ID
  3. Automatic Updates: When state changes, context is automatically updated
  4. Message Preparation: When sending messages, serialize() converts context to array
  5. Priority Sorting: Context items are sorted by priority (higher first)
  6. Backend Delivery: Context is included in the request payload to your API route
  7. AI Integration: Your backend can access structured context for the AI model

Next

Continue to Focus Items →

Last updated on