iT邦幫忙

2023 iThome 鐵人賽

DAY 13
0
Modern Web

TypeScript 啟動!系列 第 13

[Day 13] TypeScript React 初次使用

  • 分享至 

  • xImage
  •  

React 簡介

當我們使用 **create-react-app (CRA)**來建立一個新的 React 專案的時候,專案的結構大致上會像這樣。

dialogue-project/
|-- node_modules/
|-- public/
|   |-- index.html
|   |-- manifest.json
|   |-- favicon.ico
|-- src/
|   |-- App.tsx
|   |-- index.tsx
|   |-- react-app-env.d.ts
|   |-- logo.svg
|-- package.json
|-- tsconfig.json

首先我們先大概了解一下每個資料夾跟主要檔案負責的事項吧~

  • node_modules/: 這個資料夾儲存了專案的所有依賴套件。當你使用 npm installyarn add 安裝新的套件時,套件都會放在這裡。
  • public/: 這裡儲存了靜態資源,如 index.html 和其他可能的靜態檔案。這些檔案在建構過程中會被複製到輸出資料夾,而不會被 Webpack(專案能打包成瀏覽器吃的)進行任何處理。
  • src/: 這是專案主要的程式碼所在地,包括 React 組件、樣式和其他 JS/TS 程式碼。
    • App.tsx: 這是主要的 React 組件,默認會顯示 CRA 的 logo 和一些入門資訊。
    • index.tsx: 這裡是你專案的入口點。它渲染 <App /> 組件( App.tsx )到 index.html 中的一個 div 元素。
  • package.json: 描述了專案的套件版本和其他設定,如自定義快捷命令。
  • tsconfig.json: TypeScript 的配置文件,描述了如何進行 TypeScript 的編譯。

對於專案有大致上的聊解之後,我們就可以開始進行之前對話小遊戲的建置了,如果要進行之前我們得先建立一個主要概念就是 「React 是一個陳述式、高效且具有彈性的 JavaScript 函式庫,用以建立使用者介面。它讓你使用小巧而獨立的組件(component ),來建立複雜的 UI。」。

也就是說我們在建立的時候必須盡可能小而巧,這也多虧他原先的組件( component)、props(屬性,父傳子) 和 state(狀態、私有資料)、單向資料流、虛擬 DOM(有變化才會更新)。

React 實戰

回歸正題,如果要套用對話小遊戲的話,首先需要一個(按鈕來控制對話視窗)組件(component),並且會有自己的 state (私有的對話視窗的文字)。

Step1. 創建組件( component )

首先在 dialogue-project/src/ 下建立一個 DialougueComponent 的資料夾。

並建立兩個檔案 DialogueBox.tsxtype.tsx

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

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

// DialogueBox.tsx 
import React, { useState } from 'react';
import { DialogueProps, European, Asian, Person } from './type'
const DialogueBox: React.FC<DialogueProps> = () => {
    const [currentDialogueIndex, setCurrentDialogueIndex] = useState<number>(0);

    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 proceedToNextDialogue = () => {
        setCurrentDialogueIndex(prevIndex => prevIndex + 1);
    };
  return (
    <div>
      {currentDialogueIndex < combinedDialogues.length ? (
        <div>
            <p> {combinedDialogues[currentDialogueIndex].person.name}: {combinedDialogues[currentDialogueIndex].text} </p>
            <button onClick={ proceedToNextDialogue }>Next</button>
        </div>
      ) : (
        <div> <p>End of the dialogue.</p></div>
      )}
    </div>
  );
};

export default DialogueBox;
// type.tsx

export type DialogueProps = {
};

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[]) {}
}

完成後組件( component )建立後,就可以回到 APP.tsx 上去編寫一點點小地方。

// App.tsx

import React from 'react';
import DialogueBox from './DialogueComponentes/DialogueBox';

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

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

export default App;

接下來在專案底下運行指令 npm start 就可以看到跟之前一樣的效果。

https://ithelp.ithome.com.tw/upload/images/20230928/20163107C3o7JdL8Jn.png

https://ithelp.ithome.com.tw/upload/images/20230928/20163107Zjj8307mPV.png

這樣就達成跟之前一樣的目的了,明天就來盡可能完善以及分開雜亂的程式碼,順便用上 props 來傳遞資料。


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

尚未有邦友留言

立即登入留言