简体   繁体   English

使用 React Hooks 将延迟添加到地图中

[英]Add delay into a map with React Hooks

I have tried solutions related with Javascript and React using state, but I can't do it with Hooks.我已经尝试过使用 state 与 Javascript 和 React 相关的解决方案,但我不能用 Hooks 做到这一点。 I want to add 3 seconds delay for each element that I'm rendering on array.map我想为我在array.map呈现的每个元素添加3 秒延迟

import React, { useState } from 'react';

const DelayMapHooks = () => {
    
    const [array, setArray] = useState([1, 2, 3])
    return (
        <div>
            {
                array.map((elem, key) => {
                    // ADD DELAY HERE FOR EACH ELEMENT
                    return( <div>Number: {elem}</div> )
                })
            }
        </div>
    );
};

export default DelayMapHooks;

I have tried adding an await/async immediately after the map, using await delay(3000) with the function我尝试在地图后立即添加一个 await/async,使用await delay(3000)和函数

const delay = ms => {return(new Promise(res => setTimeout(res, ms)))} const 延迟 = ms => {return(new Promise(res => setTimeout(res, ms)))}

But it doesn't work, showing the error: Objects are not valid as a React child (found: [object Promise]) .但它不起作用,显示错误: Objects is not valid as a React child (found: [object Promise]) Appreciated any help.感谢任何帮助。

You can't block the render method like that, render should run synchronously.你不能像那样阻塞渲染方法,渲染应该同步运行。 This can be done with useEffect though, you need to modify the state of the array each period.这可以通过 useEffect 来完成,您需要在每个周期修改数组的状态。 React will then reconcile the DOM and render an extra element every second.然后 React 将协调 DOM 并每秒渲染一个额外的元素。

useEffect(() => {
  const interval = setInterval(() => {
   // You'd want an exit condition here
  setArray(arr => [...arr, arr.length + 1]);
}, 1000);

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

Does this work for you?这对你有用吗? The delay needs to be handled through state.延迟需要通过状态处理。 Either adding the items over time or a visibility property.随着时间的推移添加项目或可见性属性。

import React, { useEffect, useState } from "react";

const DelayMapHooks = () => {
  const [array, setArray] = useState([]);

  useEffect(() => {
    for (let i = 1; i <= 3; i++) {
      setTimeout(() => setArray((prevState) => [...prevState, i]), 3000 * i);
    }
  }, []);

  return (
    <div>
      {array.map((elem, key) => {
           return <div>Number: {elem}</div>;
      })}
    </div>
  );
};

export default DelayMapHooks;

You could still use delay, but require some more works你仍然可以使用延迟,但需要更多的工作

  • iterate array with delay using IIFE async function使用 IIFE 异步函数延迟迭代array
  • after delay, set the element to be displayed and have a useEffect hook to listen to that update, and then append the to-be-displayed element to a new array using for rendering延迟后,设置要显示的元素并有一个useEffect钩子来监听该更新,然后将要显示的元素附加到一个新的数组中用于渲染
const [array] = React.useState([1, 2, 3, 4, 5])
const [displayArray, setDisplayArray] = React.useState([])
const [displayEl, setDisplayEl] = React.useState()

const delay = (ms) =>
  new Promise((res) => {
    setTimeout(() => {
      res()
    }, ms)
  })

React.useEffect(() => {
  (async function () {
    for (let el of array) {
      await delay(1000)
      setDisplayEl(el)
    }
    setDisplayEl(undefined)
  })()
}, [array])

React.useEffect(() => {
  displayEl && setDisplayArray((prev) => [...prev, displayEl])
}, [displayEl])

return (
  <div className="App">
    <h1>Hello CodeSandbox</h1>
    {displayArray.map((elem, key) => (
      <div key={key}>Number: {elem}</div>
    ))}
  </div>
)

Codesandbox for demo (refresh to see from the beginning)用于演示的 Codesandbox(从头开始刷新)

编辑可疑的威尔逊 3s78d

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

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