简体   繁体   English

在 React 中每两秒更改一次占位符文本

[英]Change placeholder text every two seconds in React

I'm trying to change the set state value every two seconds and can run in a loop but that does not seem to work with the below logic.我正在尝试每two更改一次设置的 state 值,并且可以循环运行,但这似乎不适用于以下逻辑。

Excerpt from my code摘自我的代码

 const placeholderText = ["one", "two", "three"];
  const [state, setState] = useState("");

  useEffect(() => {
    placeholderText.map((val, index) =>
      setTimeout(() => {
        setState(placeholderText[index]);
      }, 2000)
    );
  }, []);

  console.log(state);

When I try to console log the state , I get three values at a time after two seconds.当我尝试控制台记录state时,两秒后我一次得到三个值。 How can I set the state every two seconds and run it in a loop so that it keeps changing?如何每两秒设置一次 state 并循环运行以使其不断变化?

I created a working example using CodeSandbox .我使用CodeSandbox创建了一个工作示例。 Could anyone please help?有人可以帮忙吗?

You can make use of setInterval instead of setTimeout .您可以使用setInterval而不是setTimeout

Also, we can simplify the implementation in such a way that, we don't have to store the actual text in the state, rather we can store the index.此外,我们可以通过这样一种方式简化实现,我们不必将实际文本存储在 state 中,而是可以存储索引。 And update the same after the stipulated interval.并在规定的时间间隔后更新。

 const {useState, useEffect} = React; const placeholderText = ["one", "two", "three"]; const Test = () => { const [index, setIndex] = useState(0); useEffect(() => { const timer = () => { setIndex(prevIndex => { if(prevIndex === placeholderText.length - 1){ return 0; } return prevIndex + 1; }) }; setInterval(timer, 2000); //cleanup function in order clear the interval timer //when the component unmounts return () => { clearInterval(timer); } }, []); return <p>{placeholderText[index]}</p> } ReactDOM.render(<Test />, document.getElementById("react"));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script> <div id="react"></div>

Here, in the example for the simplicity I have used placeholderText outside the component.在这里,为了简单起见,我在组件外部使用了placeholderText This can be passed as prop to the component and use in the component like below and use the same as dependency to the useEffect hook.这可以作为 prop 传递给组件并在组件中使用,如下所示,并使用与useEffect挂钩的相同依赖项。

ReactDOM.render(<Test text={placeholderText}/>, document.getElementById("react"));

You are scheduling them all at the same time so they appear at the same time 2 secs later.您正在同时安排它们,因此它们会在 2 秒后同时出现。 I would do it like so:我会这样做:

import React, { useState, useEffect } from "react";
import "./styles.css";

const delayExecution = (mls) => {
  return new Promise((resolve) => {
    setTimeout(() => resolve("ok"), mls);
  });
};

export default function App() {
  const placeholderText = ["one", "two", "three"];
  const [state, setState] = useState("");

  const changePlaceholder = async () => {
    for (let i = 0; i < placeholderText.length; i++) {
      await delayExecution(2000);
      setState(placeholderText[i]);
    }
  };

  useEffect(() => {
    changePlaceholder();
  }, []);

  return (
    <div className="App">
      <input type="text" placeholder={state} />
    </div>
  );
}

delayExecution resolves a promise after a set number of millisecs and thus can be awaited. delayExecution在设定的毫秒数后解析 promise,因此可以等待。 The async function changePlaceholder does the rest.异步 function changePlaceholder执行 rest。

Sandbox: https://codesandbox.io/s/priceless-worker-4v4yc?file=/src/App.js沙盒: https://codesandbox.io/s/priceless-worker-4v4yc?file=/src/App.js

You can use setInterval instead of setTimeout to update the text in every 2 seconds.您可以使用 setInterval 而不是 setTimeout 每 2 秒更新一次文本。 Something like this:像这样的东西:

export default function App() {
  const placeholderText = ["one", "two", "three"];
  const [state, setState] = useState(0);

  useEffect(() => {
    setInterval(() => {
      setState((s) => (s + 1));
    }, 2000);
  }, []);

  const placeholder = placeholderText[state % placeholderText.length]
  return (
    <div className="App">
      <h1>Hello CodeSandbox {placeholder}</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

Its happening because of closure.它的发生是因为关闭。 If you want to change in each 2s.如果你想在每 2 秒内更换一次。 You need setInterval not setTimeout .您需要setInterval而不是setTimeout One way to tackle this use IIFE function so that it uses each loop value in setInterval instead of loop final one.解决此问题的一种方法是使用 IIFE function 以便它使用setInterval中的每个循环值而不是循环最后一个值。 Here is the code:这是代码:

import React, { useState, useEffect } from "react";
import "./styles.css";

export default function App() {
  const placeholderText = ["one", "two", "three"];
  const [state, setState] = useState(0);

  useEffect(() => {
    let interval;

    interval = setInterval(() => {
      setState(function (prev) {
        if (prev === 2) {
          setState(0);
        } else {
          setState(prev + 1);
        }
      });
    }, 2000);

    return () => {
      interval && clearInterval(interval);
    };
  }, []);

  console.log(placeholderText, state);
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      {placeholderText[state]}
    </div>
  );
}

here is the demo: https://codesandbox.io/s/magical-swirles-83d8m?file=/src/App.js:0-718这是演示: https://codesandbox.io/s/magical-swirles-83d8m?file=/src/App.js:0-718

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM