Skip to main content

Overview

SAAC Frontend uses React 19 with TypeScript for building type-safe, modern components. The project leverages React’s latest features including hooks, Fast Refresh, and the new JSX transform.

Main App Component

The default App.tsx demonstrates core React patterns:
src/App.tsx
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'

function App() {
  const [count, setCount] = useState(0)

  return (
    <>
      <div>
        <a href="https://vite.dev" target="_blank">
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://react.dev" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
      <div className="card">
        <button onClick={() => setCount((count) => count + 1)}>
          count is {count}
        </button>
        <p>
          Edit <code>src/App.tsx</code> and save to test HMR
        </p>
      </div>
      <p className="read-the-docs">
        Click on the Vite and React logos to learn more
      </p>
    </>
  )
}

export default App

Key Features

State Management

Using useState hook for reactive state

Asset Imports

Import images directly with proper typing

CSS Modules

Component-scoped styles via imports

Event Handlers

Type-safe event handling with TypeScript

React 19 Features

React 19 includes all modern hooks out of the box:
import { useState, useEffect, useRef, useMemo, useCallback } from 'react'

function ExampleComponent() {
  const [state, setState] = useState(initialValue)
  const ref = useRef(null)
  
  useEffect(() => {
    // Side effects
    return () => {
      // Cleanup
    }
  }, [dependencies])
  
  const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b])
  const memoizedCallback = useCallback(() => doSomething(a, b), [a, b])
  
  return <div ref={ref}>Content</div>
}

Component Patterns

Functional Components with TypeScript

1

Basic Function Component

function Greeting() {
  return <h1>Hello, World!</h1>
}

export default Greeting
2

Component with Props

interface ButtonProps {
  label: string
  onClick: () => void
  disabled?: boolean
}

function Button({ label, onClick, disabled = false }: ButtonProps) {
  return (
    <button onClick={onClick} disabled={disabled}>
      {label}
    </button>
  )
}

export default Button
3

Component with State and Effects

import { useState, useEffect } from 'react'

interface DataComponentProps {
  apiUrl: string
}

function DataComponent({ apiUrl }: DataComponentProps) {
  const [data, setData] = useState<string | null>(null)
  const [loading, setLoading] = useState(true)
  
  useEffect(() => {
    fetch(apiUrl)
      .then(res => res.json())
      .then(data => {
        setData(data)
        setLoading(false)
      })
  }, [apiUrl])
  
  if (loading) return <div>Loading...</div>
  return <div>{data}</div>
}

export default DataComponent

Component Organization

src/
├── components/
│   ├── common/          # Reusable UI components
│   │   ├── Button/
│   │   │   ├── Button.tsx
│   │   │   ├── Button.css
│   │   │   └── index.ts
│   │   └── Input/
│   │       ├── Input.tsx
│   │       └── index.ts
│   ├── features/        # Feature-specific components
│   │   ├── Auth/
│   │   └── Dashboard/
│   └── layout/          # Layout components
│       ├── Header.tsx
│       ├── Footer.tsx
│       └── Sidebar.tsx
├── App.tsx
└── main.tsx

Index Files for Clean Imports

src/components/Button/index.ts
export { default } from './Button'
export type { ButtonProps } from './Button'
Usage
import Button from './components/Button'

TypeScript Best Practices

Always define explicit interfaces for component props:
// ✅ Good
interface CardProps {
  title: string
  description?: string
  children: React.ReactNode
}

function Card({ title, description, children }: CardProps) {
  return (
    <div>
      <h2>{title}</h2>
      {description && <p>{description}</p>}
      {children}
    </div>
  )
}

// ❌ Avoid
function Card(props: any) {
  return <div>{props.title}</div>
}
Prefer explicit typing over React.FC:
// ✅ Recommended
interface Props {
  name: string
}

function Component({ name }: Props) {
  return <div>{name}</div>
}

// ⚠️ Less preferred (but valid)
const Component: React.FC<Props> = ({ name }) => {
  return <div>{name}</div>
}
Use proper React event types:
function Form() {
  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault()
    // Handle form submission
  }
  
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    console.log(e.target.value)
  }
  
  const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
    console.log('Clicked')
  }
  
  return (
    <form onSubmit={handleSubmit}>
      <input onChange={handleChange} />
      <button onClick={handleClick}>Submit</button>
    </form>
  )
}

Creating New Components

1

Create component file

touch src/components/MyComponent.tsx
2

Define props interface and component

src/components/MyComponent.tsx
interface MyComponentProps {
  title: string
  onAction?: () => void
}

function MyComponent({ title, onAction }: MyComponentProps) {
  return (
    <div>
      <h2>{title}</h2>
      {onAction && <button onClick={onAction}>Action</button>}
    </div>
  )
}

export default MyComponent
3

Add styles (optional)

import './MyComponent.css'
4

Import and use in App

src/App.tsx
import MyComponent from './components/MyComponent'

function App() {
  return (
    <MyComponent 
      title="Hello" 
      onAction={() => console.log('Action!')} 
    />
  )
}
The TypeScript configuration has strict: true enabled, which helps catch type errors early and ensures type safety throughout your components.

Asset Imports

Import assets directly in components with full type support:
// Images
import logo from './assets/logo.png'
import icon from './assets/icon.svg'

// Public assets (referenced by path)
const publicAsset = '/vite.svg'

function Component() {
  return (
    <div>
      <img src={logo} alt="Logo" />      {/* From src/assets/ */}
      <img src={icon} alt="Icon" />      {/* From src/assets/ */}
      <img src={publicAsset} alt="Public" /> {/* From public/ */}
    </div>
  )
}
The vite-env.d.ts file provides type definitions for asset imports:
src/vite-env.d.ts
/// <reference types="vite/client" />

Build docs developers (and LLMs) love