React + Vite + TS

De Banane Atomic
Version datée du 27 octobre 2024 à 21:42 par Nicolas (discussion | contributions) (→‎Responding to Events)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Aller à la navigationAller à la recherche

Links

Description

React is a library. It lets you put components together, but it doesn’t prescribe how to do routing and data fetching.
To build an entire app with React, we recommend a full-stack React framework like Next.js or Remix.

Command line

Bash.svg
# create a new project (framework: React, variant: TypeScript)
npm create vite@latest

# install the packages
npm install

# run the project
npm run dev

Basic App

public/index.html
<body>
    <!-- hosts the React application -->
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
</body>
src/main.tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { CssBaseline } from '@mui/material';

import './index.css'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <CssBaseline />
    <h1>My App</h1>
  </StrictMode>,
)
src/index.css
body {
  display: flex;
  min-height: 100vh;
}

#root {
  margin: 0 auto;
  padding: 2rem;
  text-align: center;
}
package.json
{
  "name": "vite-project",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build",
    "lint": "eslint .",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.3.1",
    "react-dom": "^18.3.1"
  },
  "devDependencies": {
    "@eslint/js": "^9.13.0",
    "@types/react": "^18.3.11",
    "@types/react-dom": "^18.3.1",
    "@vitejs/plugin-react": "^4.3.3",
    "eslint": "^9.13.0",
    "eslint-plugin-react-hooks": "^5.0.0",
    "eslint-plugin-react-refresh": "^0.4.13",
    "globals": "^15.11.0",
    "typescript": "~5.6.2",
    "typescript-eslint": "^8.10.0",
    "vite": "^5.4.9"
  }
}

Component

src/App.tsx
import { useState } from 'react'
import './App.css'

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

  return (
    <>
      <h1>My App</h1>
    </>
  )
}
Tsx.svg
import App from './App.tsx'

<App />

Styling

App.tsx
import './App.css';

<div
  id='d1'
  className="container"
  style={{ display: flex }}
></div>
App.css
#d1 { }
.container { }

CSS module

App.tsx
import styles from './App.css';

<div className={styles.container}></div>
App.module.css
.container { }

Palette and Color

Default colors
Value Color
primary blue
secondary violet
error red
warning orange
info blue
success green

Hooks

State

Allows to store values.

Tsx.svg
// items is the variable used to store the items
// setItems is a function to set a new value to items
const [items, setItems] = useState<Item[]>([]);

Effect

Allows to connect a component to an external system.

Tsx.svg
useEffect(() => {
  const fetchData = async () => {
    const result = await axios(`${API}?query=react`);
  };
  
  fetchData();
}, []);

Responding to Events

Tsx.svg
export default function Button() {
  function handleClick() {
    alert('You clicked me!');
  }

  return (
    <button onClick={handleClick}>
      Click me
    </button>
  );
}

Form

EditItemForm.tsx
import { useState } from 'react';
import { TextField, Button, Box, Typography } from '@mui/material';
import { useParams, useNavigate } from 'react-router-dom';

import SaveIcon from '@mui/icons-material/Save';
import CancelIcon from '@mui/icons-material/Cancel';

export default function EditItemForm() {
    const { id } = useParams<{ id: string }>();
    const navigate = useNavigate();

    const initialData = {
        name: id === "1" ? 'Item 1' : 'Item X',
    };

    const [name, setName] = useState<string>(initialData.name);

    const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
        e.preventDefault(); // Prevent the default form submission
        console.log('Updated Data:', { name });
        navigate('/');
    };

    const handleCancel = () => {
        navigate('/'); // Navigate back to the item list without saving changes
    };

    return (
        <Box component="form" onSubmit={handleSubmit} sx={{ mt: 3 }}>
            <Typography variant="h4" gutterBottom>
                Edit Item
            </Typography>
            <TextField
                label="Name"
                variant="outlined"
                fullWidth
                margin="normal"
                value={name}
                onChange={(e) => setName(e.target.value)}
                required
            />
            <Box>
                <Button variant="contained" color="primary" type="submit" startIcon={<SaveIcon />} sx={{ mr: 1 }}>
                    Save
                </Button>
                <Button variant="outlined" color="secondary" onClick={handleCancel} startIcon={<CancelIcon />}>
                    Cancel
                </Button>
            </Box>
        </Box>
    )
}

Visual Studio Code

Debug

Install the Debugger for Firefox extension.

.vscode/launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Firefox against localhost",
            "type": "firefox",
            "request": "launch",
            "url": "http://localhost:5173",
            "webRoot": "${workspaceFolder}"
        }
    ]
}

Naming convention

  • file name: PascalCase
Tsx.svg
// use the filename as the component name, so PascalCase
import App from './App.tsx'

Component libraries