Mobile Step 3: API Client
Connect your chat app to the Flask backend using fetch().
What You'll Learn
- Making HTTP requests with
fetch() - Async/await for asynchronous code
- Handling JSON responses
- Error handling for network requests
Step 1: Set the API Base URL
const API_BASE_URL = "http://10.0.2.2:5000";
Which URL to use:
| Environment | URL |
|---|---|
| Android emulator | http://10.0.2.2:5000 |
| iOS simulator | http://localhost:5000 |
| Physical device | http://YOUR_COMPUTER_IP:5000 |
| Expo web | http://localhost:5000 |
Find your computer's IP:
# macOS/Linux
ip addr show | grep inet
# Windows
ipconfig
Step 2: Fetch Messages on App Load
import { useEffect } from "react";
useEffect(() => {
fetchMessages();
}, []);
const fetchMessages = async () => {
try {
const response = await fetch(`${API_BASE_URL}/api/messages`);
const data: Message[] = await response.json();
setMessages(data);
} catch (err) {
console.error("Failed to fetch messages:", err);
}
};
useEffectruns once when the app loads (the[]dependency array means "run once")fetch()sends a GET request to the backendresponse.json()parses the JSON response body
Step 3: Send a Message
Replace the placeholder handleSend from step 2:
const handleSend = async () => {
const text = input.trim();
if (!text) return;
setInput(""); // Clear input immediately
setError(null);
// Add user message to the list immediately (optimistic UI)
const tempUser: Message = {
id: Date.now(),
content: text,
sender: "user",
};
setMessages((prev) => [...prev, tempUser]);
try {
const response = await fetch(`${API_BASE_URL}/api/chat`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message: text }),
});
if (!response.ok) {
const errData = await response.json();
throw new Error(errData.error || "Request failed");
}
const data = await response.json();
// Replace temp message with server-confirmed message, add AI reply
setMessages((prev) =>
prev.map((m) =>
m.id === tempUser.id ? data.user_message : m
).concat(data.ai_message)
);
} catch (err: any) {
setError(err.message || "Failed to send message");
// Mark the failed message
setMessages((prev) =>
prev.map((m) =>
m.id === tempUser.id
? { ...m, content: `${m.content} (failed)` }
: m
)
);
}
};
Step 4: Understanding fetch()
const response = await fetch(url, {
method: "POST", // HTTP method
headers: {
"Content-Type": "application/json", // Tell server we're sending JSON
},
body: JSON.stringify({ message: text }), // Convert object to JSON string
});
The await keyword pauses execution until the response comes back. Without it, the code would continue before the request finishes.
Step 5: Error Handling
try {
// Network request
} catch (err) {
// Something went wrong — no response at all (network error)
}
Two types of errors:
1. Network error — can't reach the server (caught by catch)
2. HTTP error — server responded with an error status (check response.ok)
Step 6: Test the Connection
- Start the backend:
python app/__init__.py(frombackend/) - Start the mobile app:
npx expo start(frommobile/) - Type a message and tap Send
- The message appears, and the AI should respond (if you configured OpenAI)
- If the AI doesn't respond: check the error banner
Common Issues
"Network request failed" — The app can't reach the backend: - Is the backend running? - Is the URL correct for your platform (emulator vs physical device)? - Are both devices on the same network?
JSON parse error — The response isn't valid JSON: - Check the backend terminal for errors - Test with curl to confirm the API works