You can't add AI to a React app you don't understand. Day 1 builds the foundation fast: components, props, useState, and event handlers. By the end you'll have a working React app ready for the AI layer.
Vite is significantly faster than Create React App. Use it for all new projects.
npm create vite@latest my-ai-app -- --template react
cd my-ai-app
npm install
npm run dev # opens http://localhost:5173
my-ai-app/
├── src/
│ ├── App.jsx ← root component
│ ├── main.jsx ← entry point
│ └── components/ ← your components go here
├── public/
├── index.html
└── vite.config.js
A React component is a function that returns JSX (HTML-like syntax). Components are reusable — write once, use anywhere.
// src/components/MessageCard.jsx
function MessageCard({ role, content, timestamp }) {
return (
{role}
{timestamp}
{content}
);
}
export default MessageCard;
// Usage in App.jsx
import MessageCard from './components/MessageCard';
function App() {
return (
);
}
className instead of class, self-close all tags (<img />), and wrap expressions in {}.import { useState } from 'react';
function ChatInput({ onSend }) {
const [message, setMessage] = useState('');
const [isLoading, setIsLoading] = useState(false);
function handleSubmit(e) {
e.preventDefault();
if (!message.trim()) return;
onSend(message);
setMessage(''); // clear after sending
}
return (
);
}
function MessageList({ messages }) {
return (
{messages.map((msg) => (
))}
);
}
import { useState } from 'react';
function App() {
const [messages, setMessages] = useState([
{ id: 1, role: 'assistant', content: 'Hi! Ask me anything.' }
]);
function handleSend(text) {
// Add user message
const userMsg = { id: Date.now(), role: 'user', content: text };
setMessages(prev => [...prev, userMsg]);
// We'll add the AI response in Day 2
const aiMsg = {
id: Date.now() + 1,
role: 'assistant',
content: `You said: "${text}" — AI coming in Day 2!`
};
setMessages(prev => [...prev, aiMsg]);
}
return (
AI Chat
{messages.map(msg => (
{msg.role}: {msg.content}
))}
);
}
function ChatInput({ onSend }) {
const [text, setText] = useState('');
return (
);
}
export default App;
App.jsx.MessageCard component that takes role and content as props.ChatInput component with a controlled text input and submit handler.App.jsx, add a messages state array and an onSend handler that adds the user message.useState triggers a re-render when its value changes. Always update state with the setter, never mutate directly.[...prev, newItem] to add to an array in state.key prop — use IDs, not array indexes if possible.Add a 'Clear Chat' button that resets messages to just the initial greeting. Add a message counter badge in the header showing how many messages are in the conversation.