likes
comments
collection
share

【React】使用React Hooks开发一个打字小游戏

作者站长头像
站长
· 阅读数 49

前言

本文主要内容:通过开发一个打字小游戏页面的各个功能,了解各种react hooks的使用

在之前的文章中已经介绍过useStateuseEffect这两个react hooks了,也确实在具体的开发过程中体会到了react hooks带来的便利,在下面将会介绍更多的react hooks

项目预览与分析

【React】使用React Hooks开发一个打字小游戏

可以看到程序的基本架构代码如下

import React from "react"

export default function App() {
  return (
    <div>
      <h1>How fast do you type?</h1>
      <textarea />
      <h4>Time remaining: ???</h4>
      <button>Start</button>
      <h1>Word count: ???</h1>
    </div>
  )
}

我们需要实现的功能如下:

  • 指定打字时间倒数
  • 对输入文字计数
  • 点击按钮重新开始
  • ...

useState和useEffect

获取输入的字符

要对输入的字段计数,首先要获得我们输入的字符。代码如下

const [text,setText] = useState("")

function handleChange(e) {
    const {value} = e.target
    setText(value)
}
  
   <textarea
    onChange={handleChange}
    value={text}
  />

这里textarea中的value={text}是一个先有鸡还是先有蛋的问题,总之就是我们要获取textarea的值,将其设置为state,并且重新将值设置为我们输入的。

对输入的字符计数

要实现的功能是点击start按钮就会返回text中的单词的个数,由于是个算法问题,不在这占过多的篇幅,计数的函数代码如下

  function calculateWordCount(myText) {
    const wordsArr = myText.trim().split(" ")
    return wordsArr.filter(word => word !== "").length
  }

可以看到用了三步,split是将一整个string根据空格进行分割然后生成数组,trim是去除字符串首尾的空格,filter过滤了空字符串,共同确保了能返回正确的单词数

以及对函数的调用如下 <button onClick={() => calculateWordCount(text)}>Start</button>

设置时间倒数功能

在将获得的单词计数输出到屏幕之前,先设置一个时间倒数的功能

同样是设置一个state,然后写一个倒数的函数,如下

const [timeRemaining, setTimeRemaining] = useState(5)

  useEffect(() =>{
    if(timeRemaining > 0){
      setTimeout(() => {
        setTimeRemaining(time => time - 1)
      }, 1000)
    }
  }, [timeRemaining])

如果时间大于0,那么每隔1000ms都会将time state - 1。这样就完成了时间的倒数

不过我们希望是在点击start按钮后才进行倒数,所以可以通过再添加一层验证来实现,如下

const [isTimeRunning, setIsTimeRunning] = useState(false)

  useEffect(() =>{
    if(timeRemaining > 0 && isTimeRunning){
      setTimeout(() => {
        setTimeRemaining(time => time - 1)
      }, 1000)
    }else if(timeRemaining === 0) {
      setIsTimeRunning(false)
    }
  }, [timeRemaining, isTimeRunning])
  
  <button onClick={() => setIsTimeRunning(true)}>Start</button>

设置了一个新的state,初始值为false,然后按钮函数为设置这个state为true。注意这里需要在useEffect的dependencis中加入isTimeRunning,从而让其能够运行里面的代码。

在时间为0时输出单词数

同样是设置一个state,然后在时间为0时调用之前写好的calculateWordCount函数,将函数的返回值设置为这个state的值,代码如下

const [wordCount, setWordCount] = useState(0)

    }else if(timeRemaining === 0) {
      setIsTimeRunning(false)
      setWordCount(calculateWordCount(text))
    }

结束后点击按钮重新开始

每次游戏结束后都需要刷新页面来重新开始,所以现在的需求是在按钮上设置一个可以重新开始的功能。为了重新开始,我们需要设置时间开关、剩余时间以及文本框内容,所以按钮函数如下

function startGame() {
    setIsTimeRunning(true)
    setTimeRemaining(5)
    setText("")
}

这样我们就能实现结束游戏后,点击按钮再一次开始

然而当我们多次点击会发现出现一些问题,所以设置一个点击一次后按钮失效的功能,代码如下

  <button 
    onClick={startGame}
    disabled={isTimeRunning}
  >
    Start
  </button>

当isTimeRunning,disabled为true,按钮失效。

同样也可以对textarea进行类似设置,并且设置一下textarea背景的颜色用作提示,如下

textarea:disabled {
  background-color: #a5a2a2;
}

所以目前的实现效果如下

【React】使用React Hooks开发一个打字小游戏

useRef

实现自动切换光标

接下来我们想要对功能进一步地优化,实现点击start按钮后,可以直接输入字符,而不用再点击文本输入框。

这需要用到 react hooks 中 useRef 的功能,首先定义一个useRef如下

const textBoxRef = useRef(null)

然后为需要focus的dom元素添加ref,此处给textarea添加ref={textBoxRef}

最后使用这个ref,在start按钮的函数编写语句textBoxRef.current.focus()

然而此时并不能起效果,因为textarea被disable了,所以要先textBoxRef.current.disabled = false

这样就能在点击start按钮后,自动将光标移到文本输入框中

custom hooks

生成hooks单独文件

最后对代码进行优化,为了避免App组件中的内容过多,我们创建一个useWordGame.js作为提供hooks的单独文件,需要使用时引入即可,所以将hooks相关的代码全部移到新文件中,然后使用如下代码输出

return {textBoxRef, handleChange, text, isTimeRunning, timeRemaining, startGame, wordCount}

之后就是在App中接收并使用这些输出的hooks,如下

import useWordGame from "./useWordGame"
  
  const {
    textBoxRef, 
    handleChange, 
    text, 
    isTimeRunning, 
    timeRemaining, 
    startGame, 
    wordCount
  } = useWordGame()

所以我们就完成了这个打字小游戏的开发,效果如下

【React】使用React Hooks开发一个打字小游戏

小结

粗略地使用了一些react hooks相关的内容开发了一个网页打字游戏,其中值得关注的有useRef和custom hooks两个新知识点,前者用于定位dom元素,后者是将react hooks单独生成文件的方式。

项目原地址:scrimba.com/learn/react…

我的GitHub地址:github.com/newfish-cmy…

转载自:https://juejin.cn/post/7163167702578626596
评论
请登录