首頁 > web前端 > js教程 > 如何使用 React 和 Rest API 建立網站(React 基礎知識解釋)

如何使用 React 和 Rest API 建立網站(React 基礎知識解釋)

DDD
發布: 2024-11-08 03:05:02
原創
530 人瀏覽過

How to build a website using React and Rest APIs (React basics explained)

React 和 TypeScript 是用於建立可擴展、可維護和安全網站的強大框架。 React 提供了靈活且基於元件的架構,而 TypeScript 則為 JavaScript 添加了靜態類型,以實現乾淨且可讀的程式碼。本文將引導您使用 React 和 TypeScript 設定一個簡單的網站,涵蓋入門所需的核心概念。

為什麼選擇 React 和 TypeScript?

TypeScript 在 JavaScript 開發人員中很受歡迎,因為它可以在開發過程中捕獲錯誤並使程式碼更易於理解和重構。這兩者非常適合建立現代、快速的網站和應用程序,並具有可擴展的可維護程式碼。

** 在 GitHub 上查看完整程式碼:https://github.com/alexiacismaru/techtopia/tree/main/frontend

基本的 React 概念以及如何使用它們來建立網站

讓我們為一個名為 Techtopia 的虛構遊樂園建立一個網站。我們將顯示景點等元素以及它們在地圖上的位置、登陸頁面或載入頁面。此外,我們還將允許新增/刪除頁面元素或基於變數搜尋它們。

設定

透過將其複製到終端機來建立一個空的 React 專案。

npm create vite@latest reactproject --template react-ts
登入後複製
登入後複製
登入後複製

然後執行空項目,瀏覽器視窗中將開啟一個新分頁。

cd reactproject
npm run dev
登入後複製
登入後複製
登入後複製

最終專案結構概述

reactproject/
├── node_modules/
├── public/
├── src/
│   ├── assets/
│   ├── components/
│   ├── context/
│   ├── hooks/
│   ├── model/
│   ├── services/
│   ├── App.css
│   ├── App.tsx
│   ├── index.css
│   ├── vite-env.d.ts
├── .gitignore
├── package.json
└── tsconfig.json
登入後複製
登入後複製
登入後複製

成分

元件是也可以重複使用的網頁元素。它們可以是網頁的一部分,例如頁首或頁腳,也可以是整個頁面,例如使用者清單。它就像一個 JavaScript 函數,但傳回一個渲染的元素。

export function Header() {
    return (
        <header>



<h3>
  
  
  JSX
</h3>

<p>JSX is JavaScript XML, allowing the user to write HTML-like code in .jsx files.<br>
</p>

<pre class="brush:php;toolbar:false"><button sx="{{padding:" color: onclick="{onClose}">X</button>
登入後複製
登入後複製

多倫多證券交易所

TSX 是包含 JSX 語法的 TypeScript 檔案的檔案副檔名。借助 TSX,您可以使用現有的 JSX 語法編寫經過類型檢查的程式碼。

interface RefreshmentStand {
    id: string;
    name: string;
    isOpen: boolean;
}

const Reshfresment = (props: RefreshmentStand) => {
  return (
    <div>
        <h1>{props.name}</h1>
        <p>{props.isOpen}</p>
    </div>
  );
};
登入後複製
登入後複製

碎片

片段將多個元素傳回組件。它會對元素清單進行分組,而不建立額外的 DOM 節點。

我們可以使用它們從Java 後端獲取資料(看看如何從本文建立Java 應用程式:https://medium.com/@alexia.csmr/using-bounded-contexts-to-build -a-java- application-1c7995038d30)。首先安裝 Axios 並使用應用程式中的基本後端 URL。然後,我們將創建一個使用 GET 獲取所有景點的片段。

import axios from 'axios'
import { POI } from '../model/POI'

const BACKEND_URL = 'http://localhost:8093/api'

export const getAttractions = async () => {
    const url = BACKEND_URL + '/attractions'
    const response = await axios.get<poi>(url)
    return response.data
}
</poi>
登入後複製
登入後複製

可以擴展到根據參數取得數據,POST,DELETE等

npm create vite@latest reactproject --template react-ts
登入後複製
登入後複製
登入後複製

狀態

狀態是一個 React 對象,包含有關組件的資料或資訊。元件的狀態可能會隨著時間的推移而變化,當發生變化時,元件會重新渲染。

要根據參數從清單中取得單一元素,您可以使用 useParams() 掛鉤。

cd reactproject
npm run dev
登入後複製
登入後複製
登入後複製

掛鉤

如上所示,我使用了_useAttractions()和_useTagsAttractions()。它們是鉤子,可以進行個性化以獲得您想要的任何數據。在此範例中,他們根據 ID _或 _tags 取得景點。 Hooks 只能在 React 函數元件內部調用,只能在元件的頂層調用,且不能是有條件的。

reactproject/
├── node_modules/
├── public/
├── src/
│   ├── assets/
│   ├── components/
│   ├── context/
│   ├── hooks/
│   ├── model/
│   ├── services/
│   ├── App.css
│   ├── App.tsx
│   ├── index.css
│   ├── vite-env.d.ts
├── .gitignore
├── package.json
└── tsconfig.json
登入後複製
登入後複製
登入後複製

isLoading 和 isError

為了獲得更好的 UI 體驗,最好讓使用者知道發生了什麼,即元素正在加載,或執行此操作時出現錯誤。它們首先在鉤子中聲明,然後在組件中引入。

export function Header() {
    return (
        <header>



<h3>
  
  
  JSX
</h3>

<p>JSX is JavaScript XML, allowing the user to write HTML-like code in .jsx files.<br>
</p>

<pre class="brush:php;toolbar:false"><button sx="{{padding:" color: onclick="{onClose}">X</button>
登入後複製
登入後複製

您也可以為更自訂的網站建立單獨的載入器或警報元件。

interface RefreshmentStand {
    id: string;
    name: string;
    isOpen: boolean;
}

const Reshfresment = (props: RefreshmentStand) => {
  return (
    <div>
        <h1>{props.name}</h1>
        <p>{props.isOpen}</p>
    </div>
  );
};
登入後複製
登入後複製

現在,當頁面載入時,使用者將在螢幕上看到特殊的動畫。

映射項(列表和鍵)

如果你想顯示清單中的所有元素,那麼你需要映射所有元素。

import axios from 'axios'
import { POI } from '../model/POI'

const BACKEND_URL = 'http://localhost:8093/api'

export const getAttractions = async () => {
    const url = BACKEND_URL + '/attractions'
    const response = await axios.get<poi>(url)
    return response.data
}
</poi>
登入後複製
登入後複製

您可以在此處建立一個類型,以便稍後使用表單添加更多景點:

export const addAttraction = async (attractionData: Omit<poi>) => {
    const url = BACKEND_URL + '/addAttraction'
    const response = await axios.post(url, attractionData)
    return response.data
}

export const getAttraction = async (attractionId: string) => {
    const url = BACKEND_URL + '/attractions'
    const response = await axios.get<poi>(`${url}/${attractionId}`)
    return response.data
}

export const getAttractionByTags = async (tags: string) => {
    const url = BACKEND_URL + '/attractions'
    const response = await axios.get<poi>(`${url}/tags/${tags}`)
    return response.data
}
</poi></poi></poi>
登入後複製

新增項目

我們已經創建了所需的片段和掛鉤,因此現在我們可以製作一個表單,使用者可以在其中寫入屬性並向網頁添加新的吸引力。此表單是使用 MUI 框架建立的。首先我將展示整個程式碼並分段解釋。

const { id } = useParams()
const { isLoading, isError, attraction } = useAttraction(id!)
const { tag } = useParams()
const { isLoadingTag, isErrorTag, attractions } = useTagsAttractions(tag!)
登入後複製

如果您想讓表單成為彈出視窗而不是單獨的頁面,請新增 isOpen()isClosed() 屬性。 onSubmit() 是強制性的,因為這將觸發 createPOI() 函數並將新物件新增至清單。

import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
import {POI} from "../model/./POI.ts";
import { addAttraction, getAttractions } from '../services/API.ts'
import { useContext } from 'react'

export function useAttractions() {
    const queryClient = useQueryClient()
    const {
        isLoading: isDoingGet,
        isError: isErrorGet,
        data: attractions,
    } = useQuery({
        queryKey: ['attractions'],
        queryFn: () => getAttractions(),
    })

    const {
        mutate,
        isLoading: isDoingPost,
        isError: isErrorPost,
    } = useMutation((item: Omit<poi>) => addAttraction(item), {
        onSuccess: () => {
            queryClient.invalidateQueries(['attractions'])
        },
    });

    return {
        isLoading: isDoingGet || isDoingPost,
        isError: isErrorGet || isErrorPost,
        attractions: attractions || [],
        addAttraction: mutate
    }
}
</poi>
登入後複製

為了進行使用者表單驗證,我們將安裝並匯入 Zod。在這裡聲明輸入需要什麼格式以及是否有最小或最大長度等要求。

const navigate = useNavigate()
const { isLoading, isError, attractions, addAttraction } = useAttractions()

if (isLoading) {
    return <loader></loader>
}

if (isError) {
    return <alert severity="error">Error</alert>
}
登入後複製

在元件內部,我們需要實作提交和使用者驗證。

export default function Loader() {
    return (
        <div>
            <img alt="如何使用 React 和 Rest API 建立網站(React 基礎知識解釋)" src="https://media0.giphy.com/media/RlqidJHbeL1sPMDlhZ/giphy.gif?cid=6c09b9522vr2magrjgn620u5mfz1ymnqhpvg558dv13sd0g8&ep=v1_stickers_related&rid=giphy.gif&ct=s">
            <h3>Loading...</h3>
        </div>
    )
}
登入後複製

錯誤將在表單的 TextField 中與任何其他屬性一起實作。

import { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { useAttractions } from '../hooks/usePOI.ts'
import { POI } from '../model/./POI.ts'

export default function Attractions() {
    const navigate = useNavigate()
    const { isLoading, isError, attractions, addAttraction } = useAttractions()

    return (
      <div>



<p>Create a separate file where you declare the Attraction element and its variables.<br>
</p>

<pre class="brush:php;toolbar:false">// ../model/POI.ts

export interface POI {
    id: string;
    name: string;
    description: string;
    tags: string;
    ageGroup: string;
    image: string;
}
登入後複製

確保表單可以在開始時關閉並提交。

export type CreatePOI = Omit<poi>; # id is automatically generated so we don't need to manually add it
</poi>
登入後複製

您可以在另一個元件中實現此彈出視窗。

import {CreatePOI} from "../model/./POI.ts";
import {z} from 'zod';
import {zodResolver} from "@hookform/resolvers/zod";
import {Controller, useForm} from "react-hook-form";
import {
    Box,
    Button,
    Dialog,
    DialogActions,
    DialogContent,
    DialogTitle,
    TextField,
} from '@mui/material'

interface AttractionDialogProps {
    isOpen: boolean;
    onSubmit: (attraction: CreatePOI) => void;
    onClose: () => void;
}

const itemSchema: z.ZodType<createpoi> = z.object({
    name: z.string().min(2, 'Name must be at least 2 characters'),
    description: z.string(),
    tags: z.string(),
    ageGroup: z.string(),
    image: z.string().url(),
})

export function AddAttractionDialog({isOpen, onSubmit, onClose}: AttractionDialogProps) {
    const {
        handleSubmit,
        control,
        formState: {errors},
    } = useForm<createpoi>({
        resolver: zodResolver(itemSchema),
        defaultValues: {
            name: '',
            description: '',
            tags: '',
            ageGroup: '',
            image: '',
        },
    });

    return (
        <dialog open="{isOpen}" onclose="{onClose}">
            <form onsubmit="{handleSubmit((data)"> {
                    onSubmit(data)
                    onClose()
                })} 
            >
                <div>
                    <dialogtitle>Add attraction</dialogtitle>
                    <button onclick="{onClose}">
                        X
                    </button>
                </div>
                <dialogcontent>
                    <box>
                        <controller name="name" control="{control}" render="{({field})"> (
                                <textfield label="Name" error="{!!errors.name}" helpertext="{errors.name?.message}" required></textfield>
                            )}
                        />
                        <controller name="description" control="{control}" render="{({field})"> (
                                <textfield label="Description" error="{!!errors.description}" helpertext="{errors.description?.message}"></textfield>
                            )}
                        />
                        <controller name="tags" control="{control}" render="{({field})"> (
                                <textfield label="Tags" error="{!!errors.tags}" helpertext="{errors.tags?.message}" required></textfield>
                            )}
                        />
                        <controller name="ageGroup" control="{control}" render="{({field})"> (
                                <textfield label="Age group" error="{!!errors.ageGroup}" helpertext="{errors.ageGroup?.message}" required></textfield>
                            )}
                        />
                        <controller name="image" control="{control}" render="{({field})"> (
                                <textfield label="Image" error="{!!errors.image}" helpertext="{errors.image?.message}" required></textfield>
                            )}
                        />
                    </controller></controller></controller></controller></controller></box>
                </dialogcontent>
                <dialogactions>
                    <button type="submit" variant="contained">
                        Add
                    </button>
                </dialogactions>
            </form>
        </dialog>
    )
}
</createpoi></createpoi>
登入後複製

刪除項目

建立一個使用 DELETE 的鉤子並在元件中實現它。

npm create vite@latest reactproject --template react-ts
登入後複製
登入後複製
登入後複製
cd reactproject
npm run dev
登入後複製
登入後複製
登入後複製

在迭代項目清單時包含它。

reactproject/
├── node_modules/
├── public/
├── src/
│   ├── assets/
│   ├── components/
│   ├── context/
│   ├── hooks/
│   ├── model/
│   ├── services/
│   ├── App.css
│   ├── App.tsx
│   ├── index.css
│   ├── vite-env.d.ts
├── .gitignore
├── package.json
└── tsconfig.json
登入後複製
登入後複製
登入後複製

結論

將 React 與 TypeScript 結合使用可讓您建立易於維護和擴展的動態、安全的網站。 TypeScript 的類型檢查可以防止執行階段錯誤,​​而 React 基於元件的結構可以有效地組織專案。

以上是如何使用 React 和 Rest API 建立網站(React 基礎知識解釋)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門推薦
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板