“打印"在React中一个接一个字母的字符串 [英] "Print" string letter by letter in React

查看:50
本文介绍了“打印"在React中一个接一个字母的字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个React Native组件,该组件需要显示一个动画,其中一个字符串的字母逐个字母打印.因此,从逻辑上讲,我需要在一个循环内更新一个React状态挂钩,该循环以1秒的间隔将字符串的每个字符附加到该循环.到目前为止,我有:

I have a React Native component that needs to show an Animation with the letters of a string printing letter by letter. So, logically, I need to update a React state hook inside a loop appending each character of the string to it in a 1 second interval. What I have so far is:

let [placeholder, change_placeholder] = React.useState('');
const placeholder_print = () => {
    let temp = "Search for anything"
    console.log("Value of temp is now: " + temp)
    console.log("Length of string: " + temp.length)
    for (let i = 0; i < temp.length; i++) {
        console.log("Selected character is: " + temp.charAt(i))
        change_placeholder(placeholder.concat(temp.charAt(i)))
        console.log("Placeholder is now: " + placeholder)
    }
}

以及其中带有状态钩子的React组件:

and the React component with the state hook in it:

<View>
    <Text>{placeholder}</Text>
</View>

是的,我知道这不会动画.但是在 for 的末尾, placeholder 的值在逻辑上应该是字符串本身,对吗?如果是这样,我也许可以在for循环内使用 setTimeout()解决动画部分,从而每秒运行一次.但是,这是运行 placeholder_print()时的输出:

Yes, I know that this won't animate. But in the end of the for, the value of placeholder should logically be the string itself, right? If so, I might be able to get around the animation part with setTimeout() inside the for loop to run this every second. But, this is the output when placeholder_print() is run:

[Fri Jan 15 2021 16:29:30.166]  LOG      Value of temp is now: Search
[Fri Jan 15 2021 16:29:30.168]  LOG      Length of string: 6
[Fri Jan 15 2021 16:29:30.169]  LOG      Selected character is: S
[Fri Jan 15 2021 16:29:30.170]  LOG      Placeholder is now:
[Fri Jan 15 2021 16:29:30.170]  LOG      Selected character is: e
[Fri Jan 15 2021 16:29:30.170]  LOG      Placeholder is now:
[Fri Jan 15 2021 16:29:30.171]  LOG      Selected character is: a
[Fri Jan 15 2021 16:29:30.171]  LOG      Placeholder is now:
[Fri Jan 15 2021 16:29:30.171]  LOG      Selected character is: r
[Fri Jan 15 2021 16:29:30.172]  LOG      Placeholder is now:
[Fri Jan 15 2021 16:29:30.172]  LOG      Selected character is: c
[Fri Jan 15 2021 16:29:30.172]  LOG      Placeholder is now:
[Fri Jan 15 2021 16:29:30.173]  LOG      Selected character is: h
[Fri Jan 15 2021 16:29:30.173]  LOG      Placeholder is now:

在Python甚至没有状态钩子的原始JavaScript中运行类似的逻辑时,此方法工作正常.我不知道这是否需要使用React Native中的< Animated> 组件来实现,或者这是否与React状态挂钩的工作方式有根本的不同.我被困在这里,伸出援助之手.

When running a similar logic in Python or even vanilla JavaScript with no state hooks, this works fine. I don't know if this needs to be implemented with the <Animated> component in React Native, or if it's some fundamental difference in the way React state hooks work. I'm stuck here and helping hands will be upvoted.

推荐答案

您未在for循环中看到更新的原因是 setState()是异步的,并且更新后的状态值为在 next 渲染之前不可用.因此,您只是遍历字符串,记录 current 状态值(这是一个空字符串),然后调用 setState ,一旦循环完成,该状态将被调用.请参阅:在setState()不存在之后,Console.log()返回更新状态

The reason you aren't seeing the update in your for loop is that setState() is asynchronous and the updated state value is not available until the next render. So you are just looping through your string, logging the current state value (which is an empty string) and then calling setState which will be called once the loop is finished. see: Console.log() after setState() doesn't return the updated state

在反应上下文中考虑这样的循环时,您需要考虑更大的状态/渲染周期.动画的循环"实际上是状态变化触发的连续渲染.

When thinking about a loop like this in the context of react you need to take into account the larger state/render cycle. The 'loop' of the animation is actually successive renders triggered by state changes.

useEffect 挂钩为您提供了利用此循环的内置方法,这意味着您只需要通过顺序渲染来跟踪 index (该代码段使用 useRef保留该值)并使用它来更新状态,从而触发新的渲染等.

The useEffect hook gives you a built in method of leveraging this cycle, meaning that you simply need to track index through sequential renders (the snippet uses useRef to persist the value) and use it to update state, thus triggering a new render, etc.

这是一个简短的摘要.

const App = () => {
  const [placeholder, setPlaceholder] = React.useState('');

  const
    string = 'This is the final string.',
    index = React.useRef(0);

  React.useEffect(() => {
    function tick() {
      setPlaceholder(prev => prev + string[index.current]);
      index.current++;
    }
    if (index.current < string.length) {
      let addChar = setInterval(tick, 500);
      return () => clearInterval(addChar);
    }
  }, [placeholder]);

  return (
    <div>
      {placeholder}
    </div>
  )
}


ReactDOM.render(
  <App />,
  document.getElementById("root")
);

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

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

这篇关于“打印"在React中一个接一个字母的字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆