“hello”中缺少“e”,我不知道为什么?React useState 问题

Pra*_*ane 4 html javascript reactjs react-hooks

我正在尝试制作打字效果,这是一个非常简单的逻辑,,,但我仍然无法理解为什么 hello 中的“e”总是缺少其他一切都工作正常。还没有做出闪烁的光标!!!!

代码:

import { useState } from "react";
export function Type() {
  let str = "hello my name is prateek"
  const [char, setChar] = useState("");


  function type() {
    let i = 0;

    let id = setInterval(() => {

      setChar(prev => prev + str[i]);
      //console.log(i,"i")
      // console.log(str[i])

      i++;

      if (i === str.length - 1) {
        //console.log("hello")
        clearInterval(id)
      }
    }, 1000);

  }

  return (<div>
    <h1>{char}</h1>
    <button onClick={type}>Type</button>
  </div>)
}
Run Code Online (Sandbox Code Playgroud)

输出

hllo my name is prateek
Run Code Online (Sandbox Code Playgroud)

ste*_*nja 5

我认为你可能有异步竞争条件:

一个建议:使用循环并setTimeout()延迟1000*i。循环确保您添加每个字母,延迟将相隔 1 秒添加每个字母。

另一个建议:Dan Abramov 写了一篇非常有趣的博客文章,深入探讨了这一点:使用 React Hooks 使 setInterval 具有声明性(2019)。他的解决方案探索了他编写的自定义钩子useInterval(不是 React Hooks API 的一部分),并解释了 React 渲染周期和“滑动延迟”发生的情况。

const { useState } = React;

function Type(){
  let str = "hello my name is prateek"
  const [char,setChar] = useState("");
  
  
  function type(){
    let i = 0;
      const id = setInterval(()=>{

        setChar(prev=>prev+str[i]);
        //console.log(i,"i")
        // console.log(str[i])

         i++;

         if(i === str.length-1){
           //console.log("hello")
           clearInterval(id)
         }
      },1000);
  }
  
  return <div>
    <h2>{char}</h2>
    <button onClick={type}>Type</button>
  </div>
}

function TypeWorking(){
  let str = "hello my name is prateek"
  const [char,setChar] = useState("");
  
  
  function type(){
    for(let i=0; i<str.length; i++) {
      setTimeout(()=> setChar(prev=>prev+str[i]), 1000*(i+1));
    }
  }
  
  return <div>
    <h2>{char}</h2>
    <button onClick={type}>Type</button>
  </div>
}

ReactDOM.createRoot(
  document.getElementById('app-broken')
).render(<Type />)

ReactDOM.createRoot(
  document.getElementById('app-working')
).render(<TypeWorking />)
Run Code Online (Sandbox Code Playgroud)
<h1>Question (bug)</h1>
<div id="app-broken"></div>

<h1>Working</h1>
<div id="app-working"></div>

<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
Run Code Online (Sandbox Code Playgroud)


该问题还提到了动画光标。一种想法是使用::before/::after伪元素(或另一个元素,如 a <span>)和无限 CSS 动画。