-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Doplnění materiálů pro bonusové lekce – TypeScript a Backend.
- Loading branch information
1 parent
2de46dd
commit 13b4f57
Showing
12 changed files
with
503 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
title: Úvod do backendu | ||
lead: Jak si napsat jednoduchý backend pomocí Deno | ||
access: claim | ||
sections: | ||
- ukazkovy-projekt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
## Ukázkový projekt | ||
|
||
Celá lekce se točí kolem ukázkového projektu, který najdete na GitHubu: [priklad-projekty](https://github.com/FilipJirsak-Czechitas/priklad-projekty). Popis použití je v `README` uvedeného projektu. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
title: Bonusy | ||
lead: Volitelné lekce nad rámec témat akademie, ve kterých se můžete dozvědět něco navíc. | ||
lessons: | ||
- backend | ||
- typescript |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
## API v Typescriptu | ||
|
||
Dostáváme se do závěrečné fáze naší malé aplikace. Máme komponentu `Form`, která sbírá data od uživatele a máme komponentu `Activity`, která nám zobrazí vygenerovanou aktivitu. Nezbývá než vše dát dohromady a vytvořit funkci pro vygenerování activity. Proto si ukážeme, jak používat api volání v typescritpu. | ||
|
||
Vytvoříme si asynchronní funkci `fetchData`, která na vstupu bude očekávat informaci, o jakou aktivitu má uživatel zájem. Tuto informaci pak předáme v metodě fetch v url adrese. Funkce by nám na základě typu, měla vrátit jednu náhodnou aktivitu. | ||
|
||
```js | ||
const fetchData = async (type: string) => { | ||
const res = await fetch(`http://www.boredapi.com/api/activity?type=${type}`); | ||
const data = await res.json(); | ||
console.log(data); | ||
}; | ||
``` | ||
|
||
Takto získaná data musíme uložit do stavu, abychom s nimi mohli dál pracovat. Ovšem jakého budou datového typu? V reálném životě byste dostali strukturu dat od svých Backend kolegů, ale pro náš případ bude stačit, když se podíváme do konzole, co nám naše funkce `fetchData` vrátí. Vidíme, že je to objekt tvořený několika vlastnostmi, takže si stačí podle nich vytvořit interface. | ||
|
||
```js | ||
interface ActivityDataStructure { | ||
accessibility: number | ||
activity: string; | ||
key: string; | ||
link: string; | ||
participants: number; | ||
price: number; | ||
type: string; | ||
} | ||
... | ||
const [activityData, setActivityData] = useState<ActivityDataStructure>(); | ||
``` | ||
|
||
Upravíme naši funkci `fetchData`, aby ukládala data do stavu. | ||
|
||
```js | ||
const fetchData = async (type: string) => { | ||
const res = await fetch(`http://www.boredapi.com/api/activity?type=${type}`); | ||
const data = await res.json(); | ||
setActivityData(data); | ||
}; | ||
``` | ||
|
||
Zbývají poslední dvě věci a to vytvořit si funkci, která z formuláře obdrží data od uživatele a odešleje pomocí Fetche. A pak už jen musíme zobrazit data, které obdržíme v odpověďi našeho volání. | ||
|
||
```js | ||
const handleSubmitForm = (data: FormDataStructure) => { | ||
fetchData(data.type); | ||
}; | ||
``` | ||
|
||
Výsledný kód v souboru `App.tsx` pak bude vypadat takto: | ||
|
||
```js | ||
import { useState } from 'react'; | ||
import { Activity } from './components/activity'; | ||
import { Form, FormDataStructure } from './components/form'; | ||
import './App.css'; | ||
|
||
interface ActivityDataStructure { | ||
accessibility: number | ||
activity: string; | ||
key: string; | ||
link: string; | ||
participants: number; | ||
price: number; | ||
type: string; | ||
} | ||
|
||
function App() { | ||
const [activityData, setActivityData] = useState<ActivityDataStructure>(); | ||
|
||
const fetchData = async (type: string) => { | ||
const res = await fetch(`http://www.boredapi.com/api/activity?type=${type}`); | ||
const data = await res.json(); | ||
setActivityData(data); | ||
} | ||
|
||
const handleSubmitForm = (data: FormDataStructure) => { | ||
fetchData(data.type); | ||
}; | ||
|
||
return ( | ||
<> | ||
<Form | ||
onSubmitForm={handleSubmitForm} | ||
/> | ||
{activityData && ( | ||
<Activity | ||
nameOfActivity={activityData.activity} | ||
type={activityData.type} | ||
participants={activityData.participants} | ||
price={activityData.price} | ||
/> | ||
)} | ||
</> | ||
) | ||
} | ||
|
||
export default App | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
## Cvičení: Vyzkoušej si Typescript | ||
|
||
::exc[cvlekce/typescript] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
title: Jokes generator | ||
demand: 3 | ||
--- | ||
|
||
1. Stáhni si [vzorový projekt](https://github.com/Czechitas-podklady-WEB/jokes-demo-app) v Reactu. Nainstaluj závislosti a projekt si spusť. Podívej se jak vypadá v prohlížeči a jaký je jeho kód. | ||
2. Pomocí vite a jeho šablony react-ts si vytvoř vlastní projekt. Tvým úkolem je naprogramovat stejnou aplikaci ovšem s použitím Typescriptu. | ||
3. Můžeš kopírovat libovolný kód z původní aplikace, ulehčí ti to práci. Stejně tak si můžeš zkopírovat použité styly, ale neboj se zapojit i vlastní fantazii. | ||
4. Pokud by tě napadlo jakékoli vylepšení, s chutí do něj a nezapomeň se pochlubit se svým výtvorem ostatním. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
title: Úvod do Typescriptu | ||
lead: Co je to Typescript a jak ho v Reactu používat | ||
access: claim | ||
sections: | ||
- uvod-do-typescriptu | ||
- typescript-v-reactu | ||
- komponenty-a-props | ||
- formulare-a-predavani-dat | ||
- api | ||
- cv-typescript |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
## Formuláře a předávání dat mezi komponentami | ||
|
||
V naší aplikaci budeme chtít aby si uživatel nechal vygenerovat vhodnou volnočasovou aktivitu na základě jeho preferencí. Pro začátek nám bude stačit, když ho necháme vybrat si, o jaký typ aktivity by měl zájem. A aby jsme mohli tuto informaci získat, musíme si na to vytvořit formulář, který bude uživatel vyplňovat. | ||
|
||
Vytvoříme si novou složku `Form`, kde si v `index.tsx` vytvoříme komponentu `Form`, která bude vracet jsx ve formátu: | ||
|
||
```js | ||
<form onSubmit={() => {}}> | ||
<label> | ||
<p>Your Name: </p> | ||
<input name="name" /> | ||
</label> | ||
<label> | ||
<p>Select type of Activities: </p> | ||
<select name="type"> | ||
<option value=""></option> | ||
<option value="education">Education</option> | ||
<option value="relaxation">Relaxation</option> | ||
</select> | ||
</label> | ||
<button type="submit">Submit</button> | ||
</form> | ||
``` | ||
|
||
Komponenta má jediný úkol. Bude předávat vstup od uživatele do nadřazené komponenty. V jejím inteface bude tedy jediná props, která bude očekávat callback funkci, prostřednictvím, které předá data ven. | ||
|
||
```js | ||
interface FormProps { | ||
onSubmitForm: () => void; | ||
} | ||
|
||
export const Form: React.FC<FormProps> = ({ onSubmitForm }) => { | ||
return <form onSubmit={onSubmitForm}>...</form>; | ||
}; | ||
``` | ||
|
||
Od uživatele dostaneme dva údaje, jeho jméno a preferovaný typ aktivity. Budete tedy potřebovat stav, do kterého tyto údaje uložíme a bude potřeba aby jsme určili, jakého datového typu tyto data jsou. Opět k tomu použijeme interface. | ||
|
||
```js | ||
interface FormDataStructure { | ||
name: string; | ||
type: string; | ||
} | ||
|
||
export const Form: React.FC<FormProps> = ({ | ||
onSubmitForm | ||
}) => { | ||
const [formData, setFormData] = useState<FormDataStructure>({ | ||
name: '', | ||
type: '' | ||
}); | ||
... | ||
} | ||
``` | ||
|
||
Vytvoříme si funkci `handleChange`, která nám bude poslouchat změny na formuláři, které provede uživatel a bude je ukládat do stavu. Taková funkce očekává vstup, který by měl být typu `event`, ale jaký přesně typ to je? S tím nám poradí vlastnost `onChange` u inputu. Stačí, když na ní najedem myší a typescript nám správný datový typ prozradí. | ||
|
||
```js | ||
<input | ||
name="name" | ||
onChange={(e) => { | ||
console.log(e); | ||
}} | ||
// (parameter) e: React.ChangeEvent<HTMLInputElement> | ||
/> | ||
``` | ||
|
||
Teď už víme, jaký datový typ potřebujeme a naše funkce `handleChange` bude vypadat takto: | ||
|
||
```js | ||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||
setFormData({ | ||
...formData, | ||
[e.target.name]: e.target.value, | ||
}); | ||
}; | ||
``` | ||
|
||
Ovšem ve formuláři máme ještě jiný element a to je `<select>`. Když se budeme snažit použít stejnou funkci i na něj, Typescript se bude zlobit a řekne nám, že datový typ `ChangeEvent<HTMLSelectElement>`, který má element `<select>` neodpovídá datovému typu `ChangeEvent<HTMLInputElement>`, který očekává naše funkce `handleChange` jako vstup. V takovém případě nám nezbývá nic jiného než říci, že vstup u naší funkce, může být jeden nebo druhý datový typ. V řeči Typescriptu se jedná o Union types. Jednotlivé typy od sebe oddělujeme vertikální čárou `|`. | ||
|
||
```js | ||
const handleChange = ( | ||
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement> | ||
) => { | ||
setFormData({ | ||
...formData, | ||
[e.target.name]: e.target.value, | ||
}); | ||
}; | ||
``` | ||
|
||
Teď už nám zbývá jen při odeslání formuláře předat data od uživatele ven z komponenty. Budeme tedy potřebovat funkci `handleSubmit`, která se o to postará. Protože budeme předávat do callback funkce stav `formData`, potřebujeme také upravit interface tak, aby props `onSubmitForm` očekávala vstup ve správném datovém typu. | ||
|
||
Výsledná komponenta `Form` bude vypadat takto: | ||
|
||
```js | ||
import { useState } from "react"; | ||
|
||
interface FormProps { | ||
onSubmitForm: (data: FormDataStructure) => void; | ||
} | ||
|
||
interface FormDataStructure { | ||
name: string; | ||
type: string; | ||
} | ||
|
||
export const Form: React.FC<FormProps> = ({ onSubmitForm }) => { | ||
const [formData, setFormData] = useState<FormDataStructure>({ | ||
name: "", | ||
type: "", | ||
}) | ||
|
||
const handleChange = ( | ||
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement> | ||
) => { | ||
setFormData({ | ||
...formData, | ||
[e.target.name]: e.target.value, | ||
}); | ||
}; | ||
|
||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => { | ||
e.preventDefault(); | ||
onSubmitForm(formData); | ||
}; | ||
|
||
return ( | ||
<form onSubmit={handleSubmit}> | ||
<label> | ||
<p>Your Name: </p> | ||
<input name="name" onChange={handleChange} /> | ||
</label> | ||
<label> | ||
<p>Select type of Activities: </p> | ||
<select name="type" onChange={handleChange}> | ||
<option value=""></option> | ||
<option value="education">Education</option> | ||
<option value="relaxation">Relaxation</option> | ||
</select> | ||
</label> | ||
<button type="submit">Submit</button> | ||
</form> | ||
); | ||
}; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
## Komponenty a jejich props | ||
|
||
Představte si, že máte volný večer a nevíte, jakou ativitou ho vyplnit. Vytvoříme si proto aplikaci, která nám na základě vstupů od uživatele vrátí seznam možných aktivit, kterým bychom se mohli věnovat. | ||
|
||
Naši aplikaci si vybudujeme od těch nejjednodušších částí a proto si jako první vytvoříme komponentu, která nám bude návrhy na možné aktivity zobrazovat. | ||
|
||
V našem projektu si ve složce `src` vytvoříme složku `components` a v ní složku pro naši první komponentu v Typescriptu, kterou si pojmenujeme `Activity` a vytvoříme si v ní soubor `index.tsx`. | ||
Protože používáme Typescript, tak naše soubory končí na `tsx` místo `jsx` a stejně tak soubory, které dříve používali čistý Javascript, tedy končily na `js`, budou v Typescriptu končit na `ts`. | ||
|
||
V `index.tsx` bude následující kód: | ||
|
||
```js | ||
export const Activity = () => ( | ||
<div> | ||
<h3>Name of the Activity: </h3> | ||
<p>Type: </p> | ||
<p>Participants: </p> | ||
<p>Price: </p> | ||
</div> | ||
); | ||
``` | ||
|
||
Každá komponenta v Typescriptu by měla mít definovaný svůj typ. My používáme funkční komponenty, takže naše komponenta bude mít typ `FunctionComponent` nebo zkráceně `FC` a jsme v Reactu, takže naše komponenta bude vypadat takto: | ||
|
||
```js | ||
export const Activity: React.FC = () => ( | ||
... | ||
); | ||
``` | ||
|
||
Naše komponenta bude také očekávat nějaké vstupy, tedy props, a i ty musíme definovat. V Typescriptu se props u komponent definují pomocí `interface`, který se následně předává komponentě jako tzv. generický parametr. Ten se uvádí za definici typu komponenty mezi `<>`. | ||
|
||
```js | ||
interface ActivityProps { | ||
nameOfActivity: string; | ||
type: string; | ||
participants: number; | ||
price: number; | ||
} | ||
|
||
export const Activity: React.FC<ActivityProps> = ({ | ||
nameOfActivity, | ||
type, | ||
participants, | ||
price, | ||
}) => ( | ||
<div> | ||
<h3>Name of the Activity: {nameOfActivity}</h3> | ||
<p>Type:{type} </p> | ||
<p>Participants: {participants}</p> | ||
<p>Price: {price}</p> | ||
</div> | ||
); | ||
``` | ||
|
||
Takto vytvořenou komponentu si naimportujeme do souboru `App.tsx`. Všimněte si, že nám ji Typescript červeně podtrhne a vyhodí chybu: | ||
|
||
```js | ||
import { Activity } from "./components/activity"; | ||
|
||
function App() { | ||
return ( | ||
<> | ||
<Activity /> // Error: Type '{}' is missing the following properties from | ||
type 'ActivityProps': nameOfActivity, type, participants, price ts(2739) | ||
</> | ||
); | ||
} | ||
|
||
export default App; | ||
``` | ||
|
||
Typescript nám říká, že komponenta vyžaduje vstupy, které jsou `nameOfActivity`, `type`, `participants` a `price`. Je tedy nutné tyto props u komponenty uvést a vložit do nich vstupy se správným datovým typem. Typescript nám tak napovídá, co komponenta potřebuje a zároveň nás hlídá, zda jí předáváme správné údaje. Použití naší komponenty by mělo vypadat nějak takto: | ||
|
||
```js | ||
function App() { | ||
return ( | ||
<> | ||
<Activity | ||
nameOfActivity="Learn React II." | ||
type="education" | ||
participants={40} | ||
price={1} | ||
/> | ||
</> | ||
); | ||
} | ||
``` | ||
|
||
Teď už umíme používat Typescript v jednoduchých komponenách a v další lekci si ukážeme jak pracovat s Typescriptem, pokud očekáváme nějaký vstup od uživatele a jak tento vstup předávat mezi komponentami. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
## Typescript v Reactu | ||
|
||
V předchozí sekci jsme si řekli, proč Typescript používat a jaké základní typy máme. Dost bylo teorie a teď si ukážeme, jak se Typescript používá v praxi. | ||
|
||
Vytvoříme si novou složku, kde budeme mít náš testovací projekt. Založíme si zde reaktí aplikaci, kterou si založíme pomocí vite. Podívejte se na průvodce na stránce [vitejs.dev](https://vitejs.dev/guide/#scaffolding-your-first-vite-project), kde si můžete všimnou řady předpřipravených šablon, z nichž si vybereme šablonu `react-ts`. Náš instalační script bude vypadat takto: | ||
|
||
```js | ||
npm create vite my-app -- --template react-ts | ||
``` | ||
|
||
Vite nám sestaví základní kostru projektu a taktéž za nás nastaví Typescript. V aplikaci si můžete všimnout souboru `tsconfig.json`. Jedná se o klíčový soubor, protože obsahuje konfiguraci Typescriptu. Tímto souborem říkáme Typescriptu, jak se má v našem projektu chovat a to vůči vstupním souborům, jsx kódu, modulům, které můžeme instalovat až po výstupní soubory. | ||
|
||
Nastavování `tsconfig.json` se ovšem věnovat nebudeme. Podrobné informace naleznete na stránkách [typescriptlang.org](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html). Všechno potřebné pro náš projekt už za nás nastavil vite. |
Oops, something went wrong.