從0開始手把手教你使用React Hooks開發答題App

配套影片教程

影片載入中。。。

專案程式碼結構

從0開始手把手教你使用React Hooks開發答題App

前言

React 框架的優雅不言而喻,元件化的程式設計思想使得React框架開發的專案程式碼簡潔,易懂,但早期 React 類元件的寫法略顯繁瑣。React Hooks 是 React 16。8 釋出以來最吸引人的特性之一,它簡化了原有程式碼的編寫,是未來 React 應用的主流寫法。

本文透過一個實戰小專案,手把手從零開始帶領大家快速入門React Hooks。本專案線上演示地址:

在本專案中,會用到以下知識點:

React 元件化設計思想

React State 和 Props

React 函式式元件的使用

React Hooks useState 的使用

React Hooks useEffect 的使用

React 使用 Axios 請求遠端介面獲取問題及答案

React 使用Bootstrap美化介面

Hello React

(1)安裝node。js 官網連結

(2)安裝vscode 官網連結

(3)安裝 creat-react-app 功能元件,該元件可以用來初始化一個專案, 即按照一定的目錄結構,生成一個新專案。 開啟cmd 視窗 輸入:

npm install ——g create-react-app npm install ——g yarn

(-g 代表全域性安裝)

如果安裝失敗或較慢。需要換源,可以使用淘寶NPM映象,設定方法為:

npm config set registry https://registry。npm。taobao。org

設定完成後,重新執行

npm install ——g create-react-appnpm install ——g yarn

(4)在你想建立專案的目錄下 例如 D:/project/ 開啟cmd命令 輸入

create-react-app react-exam

去使用creat-react-app命令建立名字是react-exam的專案

安裝完成後,移至新建立的目錄並啟動專案

cd react-examyarn start

一旦執行此命令,localhost:3000新的React應用程式將彈出一個新視窗。

從0開始手把手教你使用React Hooks開發答題App

專案目錄結構

右鍵react-exam目錄,使用vscode開啟該目錄。 react-exam專案目錄中有一個/public和/src目錄,以及node_modules,。gitignore,README。md,和package。json。

從0開始手把手教你使用React Hooks開發答題App

在目錄/public中,重要檔案是index。html,其中一行程式碼最重要

該div作為我們整個應用的掛載點

/src目錄將包含我們所有的React程式碼。

要檢視環境如何自動編譯和更新您的React程式碼,請找到檔案/src/App。js: 將其中的

        Learn React      

修改為

        和豆約翰 Learn React      

儲存檔案後,您會注意到localhost:3000編譯並重新整理了新資料。

從0開始手把手教你使用React Hooks開發答題App

React-Exam專案實戰

1。 首頁製作

1。安裝專案依賴,在package。json中新增:

“dependencies”: { “@testing-library/jest-dom”: “^4。2。4”, “@testing-library/react”: “^9。3。2”, “@testing-library/user-event”: “^7。1。2”, “react”: “^16。13。1”, “react-dom”: “^16。13。1”, “react-scripts”: “3。4。1”, “axios”: “^0。19。2”, “bootstrap”: “^4。5。0”, “he”: “^1。2。0”, “react-loading”: “^2。0。3”, “reactstrap”: “^8。4。1” },

執行命令:

yarn install

修改index。js,匯入bootstrap樣式

import “bootstrap/dist/css/bootstrap。min。css”;

修改App。css程式碼

html { width: 80%; margin-left: 10%; margin-top: 2%;}。ansButton { margin-right: 4%; margin-top: 4%;}

修改App。js,引入Quiz元件

import React from ‘react’;import ‘。/App。css’import { Quiz } from ‘。/Exam/Quiz’;function App() { return (

);}export default App;

在專案src目錄下新增Exam目錄,Exam目錄中新建Quiz。js

Quiz元件的定義如下: Quiz。js,引入開始頁面元件Toggle。

import React, { useState } from “react”;import { Toggle } from “。/Toggle”;export const Quiz = () => { const [questionData, setQuestionData] = useState([]); const questions = questionData。map(({ question }) => [question]); const answers = questionData。map(({ incorrect_answers, correct_answer }) => [correct_answer, incorrect_answers]。flat() ); return ( <> );};

Toggle。js,點選開始按鈕,透過axios訪問遠端介面,獲得題目及答案。

import React from “react”;import axios from “axios”;import ToggleHeader from “。/ToggleHeader”;import { Button, Form,} from “reactstrap”;export const Toggle = ({ setQuestionData,}) => { const getData = async () => { try { const incomingData = await axios。get( `https://opentdb。com/api。php?amount=10&category=18&difficulty=easy&type=multiple` ); setQuestionData(incomingData。data。results); } catch (err) { console。error(err); } }; return ( <>

{ e。preventDefault(); getData(); }} >
);};

ToggleHeader。js

import React from “react”;import { Jumbotron, Container} from “reactstrap”;export default function ToggleHeader() { return (

計算機知識小測驗

);}

https://opentdb。com/api。php介面返回的json資料格式為

{ “response_code”: 0, “results”: [{ “category”: “Science: Computers”, “type”: “multiple”, “difficulty”: “easy”, “question”: “The numbering system with a radix of 16 is more commonly referred to as ”, “correct_answer”: “Hexidecimal”, “incorrect_answers”: [“Binary”, “Duodecimal”, “Octal”] }, { “category”: “Science: Computers”, “type”: “multiple”, “difficulty”: “easy”, “question”: “This mobile OS held the largest market share in 2012。”, “correct_answer”: “iOS”, “incorrect_answers”: [“Android”, “BlackBerry”, “Symbian”] }, { “category”: “Science: Computers”, “type”: “multiple”, “difficulty”: “easy”, “question”: “How many values can a single byte represent?”, “correct_answer”: “256”, “incorrect_answers”: [“8”, “1”, “1024”] }, { “category”: “Science: Computers”, “type”: “multiple”, “difficulty”: “easy”, “question”: “In computing, what does MIDI stand for?”, “correct_answer”: “Musical Instrument Digital Interface”, “incorrect_answers”: [“Musical Interface of Digital Instruments”, “Modular Interface of Digital Instruments”, “Musical Instrument Data Interface”] }, { “category”: “Science: Computers”, “type”: “multiple”, “difficulty”: “easy”, “question”: “In computing, what does LAN stand for?”, “correct_answer”: “Local Area Network”, “incorrect_answers”: [“Long Antenna Node”, “Light Access Node”, “Land Address Navigation”] }]}

程式執行效果:

從0開始手把手教你使用React Hooks開發答題App

當前專案目錄結構為:

從0開始手把手教你使用React Hooks開發答題App

2。 問題展示頁面

Quiz。js,新增toggleView變數用來切換檢視。

const [toggleView, setToggleView] = useState(true);

Quiz。js,其中Question和QuestionHeader 元件,參見後面。

import { Question } from “。/Question”;import { Jumbotron } from “reactstrap”;import QuestionHeader from “。/QuestionHeader”;。。。export const Quiz = () => { var [index, setIndex] = useState(0); const [questionData, setQuestionData] = useState([]);。。。 return ( <> {toggleView && ( )} {!toggleView && ( )} );

使用index控制題目索引

var [index, setIndex] = useState(0);

修改Toggle。js 獲取完遠端資料,透過setToggleView(false);切換檢視。

export const Toggle = ({ setQuestionData, setToggleView, setIndex,}) => { 。。。 return ( <>

{ e。preventDefault(); getData(); setToggleView(false); setIndex(0); }} >
);};

QuestionHeader。js程式碼: 同樣的,點選 返回首頁按鈕 setToggleView(true),切換檢視。

import React from “react”;import { Button } from “reactstrap”;export default function QuestionHeader({ setToggleView, category }) { return ( <> );}

Question。js程式碼 接受父元件傳過來的question物件,並顯示。 其中he。decode是對字串中的特殊字元進行轉義。

import React from “react”;import he from “he”;export const Question = ({ question }) => { // he is a oddly named library that decodes html into string values var decode = he。decode(String(question)); return (


{decode}



);};

程式執行效果: 首頁

從0開始手把手教你使用React Hooks開發答題App

點選開始後,顯示問題:

從0開始手把手教你使用React Hooks開發答題App

當前專案目錄結構為:

從0開始手把手教你使用React Hooks開發答題App

3。 載入等待動畫

新增LoadingSpin。js

import React from “react”;import { Spinner } from “reactstrap”;export default function LoadingSpin() { return ( <> );}

修改Quiz。js

import LoadingSpin from “。/LoadingSpin”;export const Quiz = () => { const [isLoading, setLoading] = useState(false); return ( <> {toggleView && ( )} {!toggleView && (isLoading ? ( ) : ( 。。。 ))} );};

修改Toggle。js

export const Toggle = ({。。。 setLoading,}) => { const getData = async () => { try { setLoading(true); const incomingData = await axios。get( `https://opentdb。com/api。php?amount=10&category=18&difficulty=easy&type=multiple` ); setQuestionData(incomingData。data。results); setLoading(false); } catch (err) { console。error(err); } }; 。。。};

執行效果:

從0開始手把手教你使用React Hooks開發答題App

目前程式碼結構:

從0開始手把手教你使用React Hooks開發答題App

4。 實現下一題功能

新增Answer。js,使用者點選下一題按鈕,修改index,觸發主介面重新整理,顯示下一題:

import React from “react”;import { Button } from “reactstrap”;export const Answer = ({ setIndex, index }) => { function answerResult() { setIndex(index + 1); } return ( );};

修改Quiz。js,新增Answer元件:

import { Answer } from “。/Answer”;。。。 {!toggleView && (isLoading ? ( ) : ( 。。。 ))}

執行效果:

從0開始手把手教你使用React Hooks開發答題App

點選下一題:

從0開始手把手教你使用React Hooks開發答題App

5。 實現選項展示

新增AnswerList。js。 透過屬性answers傳進來的選項列表,需要被打亂順序(shuffle )

import React from “react”;import { Answer } from “。/Answer”;export const AnswerList = ({ answers, index, setIndex }) => { if (answers) var correctAns = answers[0]; const shuffle = (array) => { return array。sort(() => Math。random() - 0。5); }; const arrayCheck = (arg) => { return Array。isArray(arg) ? arg : []; }; return ( <> {shuffle(arrayCheck(answers))。map((text,ind) => ( ))} );};

修改Answer。js

import React from “react”;import he from “he”;import { Button } from “reactstrap”;export const Answer = ({ text, correct, setIndex, index }) => { function answerResult() { setIndex(index + 1); } var decode = he。decode(String(text)); return ( );};

修改Quiz。js

// import { Answer } from “。/Answer”;import { AnswerList } from “。/AnswerList”;export const Quiz = () => {。。。 return ( <> 。。。 {!toggleView && (isLoading ? ( ) : ( 。。。 ))} );};

執行效果:

從0開始手把手教你使用React Hooks開發答題App

專案結構:

從0開始手把手教你使用React Hooks開發答題App

6。 記錄使用者成績

修改quiz。js,新增setResult,並傳遞給AnswerList

export const Quiz = () => { var [result, setResult] = useState(null);。。。 return ( <> 。。。 {!toggleView && (isLoading ? ( ) : ( 。。。 ))} );};

修改AnswerList。js,傳遞setResult

import React from “react”;import { Answer } from “。/Answer”;export const AnswerList = ({ answers, index,setResult, setIndex }) => {。。。 return ( <> {shuffle(arrayCheck(answers))。map((text,ind) => ( ))} );};

修改Answer。js,使用者點選選項,回撥setResult,通知Quiz元件,本次選擇是對是錯。

import React from “react”;import { Button } from “reactstrap”;import he from ‘he’export const Answer = ({ text, correct, setResult,setIndex, index }) => { function answerResult() { setIndex(index + 1); correct === text ? setResult(true) : setResult(false); } var decode = he。decode(String(text)); return ( );};

修改Quiz。js,放一個隱藏的GameOver元件,每當index發生變化的時候,觸發GameOver中的useEffect程式碼,累計使用者答對題目的數目(setRight)

import GameOver from “。/GameOver”;export const Quiz = () => { const [right, setRight] = useState(0); const [gameIsOver, setGameOver] = useState(false); return ( <> {toggleView && ( )} {!toggleView && (isLoading ? ( ) : ( ))} );};

新增GameOver。js元件,當index === quizLength && index時,setGameOver(true)設定遊戲結束,顯示使用者得分。

import React, { useEffect } from “react”;export default function GameOver({ right, setRight, setGameOver, index, quizLength, result,}) { useEffect(() => { if (result === true) { setRight(right + 1); } if (index === quizLength && index) { setGameOver(true); } }, [index]); return

;}

7。 遊戲結束,展示使用者得分

新增ScoreBoard。js

import React from “react”;export const ScoreBoard = ({ finalScore, right }) => { // if index === 0 then right === 0 ——> this way when index is reset in toggle so is right answers const scoreFormatted = score => { if (score === 1) { return 100; } else if (score === 0) { return 0; } else { return score。toFixed(2) * 100; } } return ( <> <>

Correct Answers: {right}


Final Score: %{scoreFormatted(finalScore)}


謝謝使用

);};

ScoreHeader。js

import React from “react”;import { Button } from “reactstrap”;export default function ScoreHeader({ setGameOver, setToggleView }) { return (   );}​

修改Quiz。js,當gameIsOver 變數為true時,顯示得分頁面。

import { ScoreBoard } from “。/ScoreBoard”;import ScoreHeader from “。/ScoreHeader”;​export const Quiz = () => {​。。。​ return (   <>     {!toggleView &&       !gameIsOver &&       (isLoading ? (               ) :       (         。。。         ))}                 {gameIsOver && (                                 )}         。。。   );};​