WebTeil Studio Logo
  • Domov
  • Naše projekty
  • Cenník
  • Blog
  • O nás
  • Kontakt

WebTeil Studio

Sme tu, aby sme vaše nápady premenili na funkčné weby.

@webteil.studio

+421 944 102 674

webteil.studio@gmail.com

Navigácia

  • Domov
  • Naše projekty
  • Produkty
  • Cenník
  • Blog
  • O nás
  • Kontakt
  • QR kód generátor

Copyright © 2026 WebTeil Studio

Made with by webteil-studio.sk

Používanie cookie|Ochrana údajov
Späť na články

Vytvorenie jednoduchej ToDo aplikácie s React 18, TypeScript a Docker: sprievodca pre začiatočníkov

20.06.2024

Naučte sa, ako vytvoriť jednoduchú webovú aplikáciu typu Todo List pomocou React 18 a TypeScriptu. Prejdeme si základy vytvorenia nového React projektu, inštalácie závislostí, vytvorenia modelov a služieb a zostavenia komponentov na zobrazovanie a správu ToDo položiek.

ReactTypeScriptNode.jsDockerMaterial UIREST API
Vytvorenie jednoduchej ToDo aplikácie s React 18, TypeScript a Docker: sprievodca pre začiatočníkov

Predpoklady

Skôr než začneme, uistite sa, že máte vo svojom systéme nainštalovaný nasledujúci softvér. Tieto nástroje sú nevyhnutné na vývoj a spustenie aplikácie, ktorú budeme vytvárať:

  • Node.js: Runtime prostredie potrebné na spúšťanie JavaScriptu na strane servera. Stiahnite si ho z oficiálnej stránky Node.js.
  • NPM: Správca balíkov pre Node.js, ktorý sa používa na inštaláciu knižníc ako React. Je súčasťou Node.js.
  • Vite: Build nástroj, ktorý uľahčuje vytvorenie (scaffolding) nového projektu a jeho lokálne spúšťanie. Nainštalujte ho globálne príkazom npm install -g create-vite.
  • Docker: Platforma na vývoj, distribúciu a spúšťanie aplikácií v kontajneroch. Stiahnite si Docker z oficiálnej stránky Docker.
  • Visual Studio Code: Ľahký, ale výkonný editor zdrojového kódu pre desktop. Stiahnite si ho z oficiálnej stránky Visual Studio Code.
  • Zdrojový kód: Zdrojové súbory k tomuto tutoriálu nájdete na GitHub.

Vytvorenie nového React projektu

React je populárna JavaScript knižnica na tvorbu používateľských rozhraní. Umožňuje vývojárom vytvárať znovupoužiteľné UI komponenty a efektívne spravovať stav aplikácie.

V tomto projekte použijeme Vite na vytvorenie nového React projektu s TypeScriptom. Začnite vytvorením projektu nasledujúcim príkazom:

npm create vite@latest react-18-todo-list -- --template react-ts

Potom prejdite do priečinka projektu a nainštalujte predvolené závislosti:

cd react-18-todo-list
npm install # Install dependencies

Inštalácia ďalších závislostí

Material UI poskytuje robustnú sadu komponentov pre React. Nainštalujte ho spolu s ďalšími závislosťami:

npm install @mui/material @emotion/react @emotion/styled
npm install @fontsource/roboto
npm install @mui/icons-material
npm install axios

Do súboru main.tsx pridajte font Roboto:

import "@fontsource/roboto/300.css";
import "@fontsource/roboto/400.css";
import "@fontsource/roboto/500.css";
import "@fontsource/roboto/700.css";

Vytvorenie modelu a služby

Definujte Todo model v src/models/Todo.ts:

export default interface ToDo {
  id: number;
  name: string;
  isDone: boolean;
}

Tento model reprezentuje jednu Todo položku.

Vytvorte službu pre API volania v src/services/Todo.ts:

import axios from "axios";
const API_URL = import.meta.env.VITE_API_URL;

class ToDoService {
  http = axios.create({
    baseURL: API_URL,
  });

  async getToDos() {
    const response = await this.http.get("/todos");
    return response.data;
  }

  async addToDo(name: string) {
    const response = await this.http.post("/todos", {
      name,
    });
    return response.data;
  }

  async updateToDo(id: number, name: string, isDone: boolean) {
    const response = await this.http.put(`/todos/${id}`, {
      name,
      isDone,
    });
    return response.data;
  }

  async deleteToDo(id: number) {
     response =  ..();
     response.;
  }
}

   ();

Táto služba obsluhuje všetky HTTP požiadavky smerom na backend.

Vytváranie komponentov

Používateľské rozhranie aplikácie budeme vytvárať v priečinku src/components.

Vytvorte nový súbor ToDoList.tsx s nasledujúcim obsahom:

import { Checkbox, List, ListItem, ListItemText } from "@mui/material";
import ToDo from "../models/ToDo";
import ToDoService from "../services/ToDo";
import IconButton from "@mui/material/IconButton";
import DeleteIcon from "@mui/icons-material/Delete";

interface ToDoListProps {
  toDos: ToDo[];
  onLoadToDos: () => void;
}

export default function ToDoList({ toDos, onLoadToDos }: ToDoListProps) {
  const handleCheckTodo = (toDo: ToDo) => async () => {
    await ToDoService.updateToDo(toDo.id, toDo.name, !toDo.isDone);
    onLoadToDos(); // Reload the toDos state from the server
  };

  const handleRemoveTodo = (toDo: ToDo) => async () => {
    await ToDoService.(toDo.);
    ();
  };

   (
    
        );
      })}
    </>
  );
}

Tento komponent zobrazí zoznam Todo položiek. Zároveň umožní používateľovi označiť položku ako hotovú alebo ju odstrániť.

Vytvorte nový súbor NewToDo.tsx s nasledujúcim obsahom:

import { Button, TextField } from "@mui/material";
import { useState } from "react";
import ToDoService from "../services/ToDo";

interface NewToDoProps {
  onLoadToDos: () => void;
}

export default function NewToDo({ onLoadToDos }: NewToDoProps) {
  const [newToDoName, setNewToDoName] = useState<string>("");

  const handleSubmitForm = async (e: React.FormEvent) => {
    e.preventDefault(); // Prevent the default form submission
    if (!newToDoName) return; // Prevent adding empty to-do
    await ToDoService.addToDo(newToDoName);
    setNewToDoName(""); // Clear the input field
    onLoadToDos();
  };

  return (
    <>
      <form onSubmit={handleSubmitForm}>
        <TextField
          fullWidth
          label="New To-Do"
          variant="outlined"
          =
          = => setNewToDoName(e.target.value)}
        />
        
          Add
        
      
    
  );
}

Tento komponent umožní používateľovi pridávať nové Todo položky do zoznamu.

Aby sme tieto komponenty prepojili, vytvoríme nový súbor App.tsx v priečinku src. Vite scaffolding obsahuje predvolené CSS, ktoré nahradíme vlastným:

import "./App.css";
import { useEffect, useState } from "react";
import ToDo from "./models/ToDo";
import ToDoList from "./components/ToDoList";
import ToDoService from "./services/ToDo";
import { Container, Grid } from "@mui/material";
import NewToDo from "./components/NewToDo";

function App() {
  const [toDos, setToDos] = useState<ToDo[]>([]);

  // Initialize the toDos state with the data from the server
  useEffect(() => {
    loadToDos();
  }, []);

  const loadToDos = async () => {
    const data = await ToDoService.getToDos();
    setToDos(data);
  };

  return (
    <Container maxWidth="sm" sx={{ paddingTop: 2 }}>
      <Grid
        container
        direction="row"
        justifyContent=
        =
        =
      >
        
           loadToDos()} />
        

        
           loadToDos()} />
        
      
    
  );
}

  ;

Skôr než aplikáciu spustíme, potrebujeme v koreňovom priečinku projektu vytvoriť súbor .env s nasledujúcim obsahom:

VITE_API_URL=http://localhost:5277/api
VITE_PORT=5173

Tento súbor bude obsahovať URL backend API a port, na ktorom pobeží frontend.

Spustenie aplikácie

Skôr než aplikáciu spustíme, je potrebné spustiť backend server vytvorený v predchádzajúcom článku.

Teraz môžeme spustiť frontend aplikáciu nasledujúcim príkazom:

npm run dev # Start the project in developer mode

Dockerizácia aplikácie

Docker je silný nástroj na balenie aplikácií a ich závislostí do kontajnerov, ktoré sa dajú spustiť na akomkoľvek systéme s nainštalovaným Dockerom. Kontajnerizáciou zabezpečíte konzistentné správanie aplikácie v rôznych prostrediach, čo uľahčuje nasadenie aj správu.

Keď aplikáciu dôkladne otestujete a potvrdíte, že funguje podľa očakávaní, ďalším krokom je pripraviť ju na nasadenie pomocou Dockeru. Tento proces zahŕňa vytvorenie Docker image, ktorý bude obsahovať vašu aplikáciu aj jej prostredie.

Začnite tým, že v koreňovom priečinku projektu vytvoríte Dockerfile. Tento súbor obsahuje inštrukcie na zostavenie Docker image. Do Dockerfile pridajte nasledujúci obsah:

FROM node:20.11 as build-stage
WORKDIR /app
COPY package*.json /app/
RUN npm install
COPY . /app/

RUN npm run build

FROM nginx:stable-alpine
WORKDIR /usr/share/nginx/html
RUN rm -rf ./*
COPY --from=build-stage /app/dist/ .

# Copy the custom Nginx configuration
COPY nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 5173

CMD ["nginx", "-g", "daemon off;"]

Otvorte terminál a prejdite do priečinka, kde sa nachádza Dockerfile. Docker image zostavíte nasledujúcim príkazom:

docker build -t react-18-todo-list .

Tento príkaz priradí zostavenému image názov (tag), aby sa naň dalo neskôr jednoducho odkazovať.

Po zostavení image ho môžete spustiť ako kontajner. Kontajner spustíte nasledujúcim príkazom:

docker run --rm -it -p 5173:5173 react-18-todo-list

Tento príkaz nastaví kontajner tak, aby sa po zastavení automaticky odstránil (--rm), a namapuje port 5173 z vášho lokálneho počítača do kontajnera, takže aplikáciu budete používať rovnako, ako keby bežala lokálne.

Vaša aplikácia teraz beží v Docker kontajneri a môžete ju otvoriť v prehliadači na adrese http://localhost:5173.

Záver

V tomto tutoriáli sme si ukázali, ako vytvoriť jednoduchú webovú aplikáciu typu Todo List pomocou React 18 a TypeScriptu. Prešli sme si základy vytvorenia nového React projektu, inštalácie závislostí, vytvorenia modelov a služieb a zostavenia komponentov na zobrazovanie a správu Todo položiek.

Ak vám bol tento tutoriál užitočný, pokojne ho zdieľajte s ďalšími, ktorým by mohol pomôcť. A ako vždy, ak potrebujete pomoc alebo máte návrhy, zanechajte komentár alebo otázku nižšie.

Späť na články
const
await
this
http
delete
`/todos/${id}`
return
data
export
default
new
ToDoService
deleteToDo
id
onLoadToDos
return
<List dense sx={{ alignContent: "center", }} > {toDos.map((toDo) => { return ( <ListItem key={toDo.id} secondaryAction={ <> <Checkbox edge="end" onChange={handleCheckTodo(toDo)} checked={toDo.isDone == true} /> <IconButton aria-label="delete" size="large" onClick={handleRemoveTodo(toDo)} > <DeleteIcon /> </IconButton> </> } > <ListItemText>{toDo.name}</ListItemText> </ListItem>
List
value
{newToDoName}
onChange
{(e)
<Button sx={{ marginTop: 1 }} type="submit" variant="contained">
</Button>
</form>
</>
"center"
alignItems
"center"
spacing
{2}
<Grid item xs={8}>
<NewToDo onLoadToDos={() =>
</Grid>
<Grid item xs={8}>
<ToDoList toDos={toDos} onLoadToDos={() =>
</Grid>
</Grid>
</Container>
export
default
App