iT邦幫忙

2023 iThome 鐵人賽

DAY 14
0
Modern Web

TypeScript 啟動!系列 第 14

[Day 14] TypeScript React 初次使用 II

  • 分享至 

  • xImage
  •  

React 實戰 II

昨天我們的專案文件大概如下

.
├── README.md
├── package-lock.json
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
├── src
│   ├── App.css
│   ├── App.test.tsx
│   ├── App.tsx
│   ├── DialogueComponentes
│   │   ├── DialogueBox.tsx
│   │   └── type.tsx
│   ├── index.css
│   ├── index.tsx
│   ├── logo.svg
│   ├── react-app-env.d.ts
│   ├── reportWebVitals.ts
│   └── setupTests.ts
└── tsconfig.json

昨天我們創建了兩個檔案 DialogueBox.tsxtype.tsx ,會發現DialogueBox.tsx 處理的事項好像有點雜亂,這時我們可以進行分開,讓一個 Dom 只處理一件事情,例如將 DialogueBox.tsx 拆分成 UI 和 對話邏輯,為此我會建立一個新的檔案叫做 DialogueManager.tsx 來處理對話邏輯而DialogueBox.tsx 專心處理呈現的方式即可。另外一件事情就是我會使用 type.tsx 內的 DialogueProps 變數,作為我傳遞資訊的用途。

Step1. 創建組件( component )

首先在 dialogue-project/src/ 下建立一個 DialougueComponent 的資料夾。並建立新檔案 DialogueManager.tsx

  • DialogueBox.tsx :用於顯示對話的視窗。
  • type.tsx :用於定義型別。
  • DialogueManager.tsx :用於處理對話過程。

小心檔案名稱不要取名為 ts 了,我們需要取名為 tsx 這樣才能讓 TypeScript 吃到 JSX 的語法。(JSX 可以讓 JavaScript 內吃到 XML/HTML 語法)

// DialogueManager
import React, { useState } from 'react';
import { European, Asian, Person } from './type';
import DialogueBox from './DialogueBox';

const DialogueManager: React.FC = () => {
    const peter = new European("Peter", ["你好!", "歐洲真的很美!", "我們一天只要上五小時的班。"]);
    const lee = new Asian("Lee", ["嗨!", "真的嗎?那真的太棒了!", "Emotional damage, 受到 1000000 點傷害 QQ"]);
    
    const combinedDialogues: { person: Person, text: string }[] = [];
    for(let i = 0; i < Math.max(peter.dialogues.length, lee.dialogues.length); i++) {
        if (peter.dialogues[i]) {
            combinedDialogues.push({ person: peter, text: peter.dialogues[i] });
        }
        if (lee.dialogues[i]) {
            combinedDialogues.push({ person: lee, text: lee.dialogues[i] });
        }
    }

    const [currentDialogueIndex, setCurrentDialogueIndex] = useState<number>(0);
    const proceedToNextDialogue = () => {
        setCurrentDialogueIndex(prevIndex => prevIndex + 1);
    };

    return (
        <DialogueBox 
            dialogue={combinedDialogues[currentDialogueIndex]}
            onNext={proceedToNextDialogue}
            isEnd={currentDialogueIndex >= combinedDialogues.length}
        />
    );
};

export default DialogueManager;

將原先 DialogueBox.tsx 上的繁雜運算過程,搬移至 DialogueManager.tsx 上,並透過 Props 進行資料上的傳遞。

// DialogueBox
import React from 'react';
import { DialogueProps } from './type';

const DialogueBox: React.FC<DialogueProps> = ({ dialogue, onNext, isEnd }) => {
    return (
        <div>
            {!isEnd ? (
                <div>
                    <p> {dialogue.person.name}: {dialogue.text} </p>
                    <button onClick={ onNext }>Next</button>
                </div>
            ) : (
                <div> <p>End of the dialogue.</p></div>
            )}
        </div>
    );
};

export default DialogueBox;

DialogueBox.tsx 修改成專注於 UI 呈現上,並透過父組件( DialogueManager.tsx )傳遞來的資料進行畫面切換。

// type.tsx
export type DialogueProps = {
    dialogue: { person: Person, text: string };
    onNext: () => void;
    isEnd: boolean;
};

export type Person = {
    name: string;
    dialogues: string[];
};
  
export class European implements Person {
    constructor(public name: string, public dialogues: string[]) {}
}

export class Asian implements Person {
    constructor(public name: string, public dialogues: string[]) {}
}

開始使用之前的定義好的 DialogueProps 並把參數決定好。

// app.tsx
import React from 'react';
import DialogueManager from './DialogueComponentes/DialogueManager';

const App: React.FC = () => {

  return (
    <div className="App">
      <DialogueManager />
    </div>
  );
}

export default App;

app.tsx 上更改呼叫為 DialogueManager 。接下來在專案底下運行指令 npm start 就可以看到跟之前一樣的效果。

至此,我們成功地完成了一個 React 的小專案。從這個專案,不僅可以看到React的強大,還能夠深刻體會到 React 在前端開發中的便捷性。從組件的拆分、State 的管理到 Props 的傳遞,每一步都讓我對 React 的概念有了更深入的理解。總之,完成這個小專案只是我學習的開始,接下來,我們還有更多的 TypeScript 知識需要去探索和學習。 希望最後能完成另一個小專案。


上一篇
[Day 13] TypeScript React 初次使用
下一篇
[Day 15] TypeScript 泛型
系列文
TypeScript 啟動!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言