React 18 with Vite provides a fast, lightweight development experience for building modern single-page applications.
Overview
React 18 is perfect for simple client-side applications, learning projects, and SPAs that don’t require server-side rendering.
Pre-installed Packages
- React 18: Latest React library with concurrent features
- Vite: Next-generation frontend tooling with fast HMR
- Chakra UI: Accessible component library with built-in theming
- Tailwind CSS: Utility-first CSS framework
- TypeScript: Full type safety
- Lucide React: Icon library
Key Features
- Fast HMR (Hot Module Replacement) with Vite
- Concurrent rendering features
- Automatic batching
- Suspense support
- Chakra UI’s accessible components
- Built-in dark mode support
Use Cases
React 18 is best suited for:
Simple SPAs
Client-side single-page applications without SSR requirements
Learning Projects
Educational projects and React practice applications
Prototypes
Quick prototypes and proof-of-concept applications
Interactive Tools
Calculators, converters, and client-side utilities
Chakra UI Components
Chakra UI provides accessible, composable components with built-in styling props and theming support.
Available Components
- Layout: Box, Container, Flex, Grid, Stack, Wrap
- Forms: Button, Input, Select, Checkbox, Radio, Switch, Textarea
- Data Display: Badge, Card, Code, Divider, Kbd, List, Stat, Table, Tag
- Feedback: Alert, Progress, Skeleton, Spinner, Toast
- Navigation: Breadcrumb, Link, Menu, Tabs
- Overlay: Drawer, Modal, Popover, Tooltip
Component Usage
Critical Rules
Main File: The entry point is src/App.tsx. Do not modify src/main.tsx.
Pre-installed: Chakra UI is already installed. Do not run installation commands for Chakra UI or Tailwind CSS.
File Conventions
- Main file:
src/App.tsx
- Entry point:
src/main.tsx (do not modify)
- Component files:
ComponentName.tsx (PascalCase)
- Hook files:
useHookName.ts (camelCase with ‘use’ prefix)
- Components directory:
src/components/
- Hooks directory:
src/hooks/
- Utils directory:
src/utils/
- Types directory:
src/types/
Component Structure
import React from 'react';
interface ComponentNameProps {
title: string;
onAction?: () => void;
}
export const ComponentName: React.FC<ComponentNameProps> = ({ title, onAction }) => {
// Component logic
return (
<div>
{/* JSX */}
</div>
);
};
Project Structure
src/
├── App.tsx # Main application component
├── main.tsx # Entry point (do not modify)
├── components/ # React components
├── hooks/ # Custom hooks
├── utils/ # Utility functions
└── types/ # TypeScript type definitions
Chakra UI Styling Props
Chakra UI components accept styling props for quick customization:
Layout Props
Responsive Props
Color Mode
import { Box, Flex } from '@chakra-ui/react';
export const App = () => {
return (
<Box
p={4} // padding
m={2} // margin
bg='blue.500' // background
color='white' // text color
borderRadius='md' // border radius
boxShadow='lg' // box shadow
>
<Flex
direction='column'
align='center'
justify='space-between'
gap={4}
>
Content here
</Flex>
</Box>
);
};
import { Box, Text } from '@chakra-ui/react';
export const App = () => {
return (
<Box
w={{ base: '100%', md: '50%', lg: '33%' }}
p={{ base: 2, md: 4, lg: 6 }}
>
<Text
fontSize={{ base: 'sm', md: 'md', lg: 'lg' }}
>
Responsive text
</Text>
</Box>
);
};
import { Box, Button, useColorMode } from '@chakra-ui/react';
export const App = () => {
const { colorMode, toggleColorMode } = useColorMode();
return (
<Box bg={colorMode === 'light' ? 'white' : 'gray.800'}>
<Button onClick={toggleColorMode}>
Toggle {colorMode === 'light' ? 'Dark' : 'Light'}
</Button>
</Box>
);
};
React Hooks
useState
useEffect
Custom Hook
import { useState } from 'react';
import { Button, Text, VStack } from '@chakra-ui/react';
export const App = () => {
const [count, setCount] = useState(0);
return (
<VStack>
<Text>Count: {count}</Text>
<Button onClick={() => setCount(count + 1)}>
Increment
</Button>
</VStack>
);
};
import { useState, useEffect } from 'react';
import { Text } from '@chakra-ui/react';
export const App = () => {
const [data, setData] = useState(null);
useEffect(() => {
// Fetch data on mount
fetch('https://api.example.com/data')
.then(res => res.json())
.then(setData);
}, []);
return <Text>{data ? JSON.stringify(data) : 'Loading...'}</Text>;
};
// src/hooks/useLocalStorage.ts
import { useState, useEffect } from 'react';
export function useLocalStorage<T>(key: string, initialValue: T) {
const [value, setValue] = useState<T>(() => {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue] as const;
}
// Usage in component
import { useLocalStorage } from './hooks/useLocalStorage';
export const App = () => {
const [name, setName] = useLocalStorage('name', '');
// ...
};
Styling with Tailwind
Combine Chakra UI with Tailwind utilities:
import { Card, CardHeader, CardBody } from '@chakra-ui/react';
export const App = () => {
return (
<Card className='max-w-md mx-auto mt-8'>
<CardHeader className='bg-gradient-to-r from-blue-500 to-purple-600'>
<h2 className='text-white text-xl font-bold'>Gradient Header</h2>
</CardHeader>
<CardBody className='p-6'>
<p className='text-gray-700'>Custom styled card</p>
</CardBody>
</Card>
);
};
Best Practices
Use functional components with hooks
// Prefer this
export const Component: React.FC = () => {
const [state, setState] = useState();
return <div />;
};
// Avoid class components
Extract custom hooks for reusable logic
Use proper key props for lists
{items.map((item) => (
<div key={item.id}>{item.name}</div>
))}
Implement error boundaries
import { Component, ErrorInfo, ReactNode } from 'react';
class ErrorBoundary extends Component<{children: ReactNode}> {
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error(error, errorInfo);
}
render() {
return this.props.children;
}
}
Use Chakra's useToast for notifications
import { useToast, Button } from '@chakra-ui/react';
export const App = () => {
const toast = useToast();
return (
<Button onClick={() => toast({
title: 'Success',
status: 'success',
duration: 3000,
})}>
Show Toast
</Button>
);
};