我正在尝试每秒一次将名称设置为消息数组一个字母,直到它读取完整消息

I am trying to set name to the message array one letter at a time every second until it reads the full message

JavaScript代码:

const [name, setName] = useState([]);
    const message = ["C", "h", "a", "s", "e", " ", "L", "i", "p", "s", "c", "o", "m", "b", " ", "W", "e", "b", " ", "D", "e", "v", "e", "l", "o", "p", "e", "r"]
    let letter = "";
    const displayName = () => {
        for(var i = 0; i<message.length; i++) {
            letter += message[i];
            console.log(letter)
            setName(letter);
            setTimeout(function(){console.log("work");}, 1000)
        }
    }
    useEffect(() => {
        displayName();
      }, []);

useEffect 调用 displayName() 函数,并且应该每秒添加一个字母来命名。当我 运行 应用程序时,完整的消息会以名称显示。但我希望它每秒添加一个字母。

下面的代码对我有用:

  const string = ['t', 'h', 'i', 's', ' ', 'i', 's', ' ', 'i', 't'];
  const [name, setName] = useState("");

  useEffect(() => {
    if(name.length === string.length) {
      console.log("no more update")
      return;
    }
    const id = setTimeout(() => {
      setName(name + string[name.length])
    }, 1000);
    return () => clearInterval(id);
  }, [name]);
  return (<div>{name}</div>);

两大要点:

  • 我认为还有使代码更漂亮和更易读的余地
  • 如果您有兴趣了解上述代码的工作原理,我建议您阅读 Guide to useEffect。它由丹·阿布拉莫夫 (Dan Abramov) 撰写。

您可以创建一个接受数组或字符串的自定义打字机挂钩,并使用 setInterval() 通过在每个间隔添加一个字符来迭代创建字符串:

const { useState, useRef, useEffect } = React;

const useTypewriter = (message = []) => {
  const [txt, setTxt] = useState('');
  
  const intervalRef = useRef();

  useEffect(() => {
    let index = 0; // init the index
    
    clearInterval(intervalRef.current); // clear the interval if message changes
    
    if(!message.length) return; // do nothing if message is empty

    intervalRef.current = setInterval(() => {
      setTxt(t => t + message[index]);
      
      index += 1;

      if(index === message.length) clearInterval(intervalRef.current); // clear interval when message ends
    }, 1000);

    return () => clearInterval(intervalRef.current); // clear interval if component is unmounted
  }, [message, intervalRef, setTxt]);
  
  return [txt];
};

const App = ({ message }) => {
  const [txt] = useTypewriter(message);
  
  return <div>{txt}</div>
};

const message = ["C", "h", "a", "s", "e", " ", "L", "i", "p", "s", "c", "o", "m", "b", " ", "W", "e", "b", " ", "D", "e", "v", "e", "l", "o", "p", "e", "r"];

ReactDOM.render(
  <App message={message} />,
  root
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>