I have tried solutions related with Javascript and React using state, but I can't do it with Hooks. I want to add 3 seconds delay for each element that I'm rendering on array.map
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
const delay = 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]). Appreciated any help.
I have tried solutions related with Javascript and React using state, but I can't do it with Hooks. I want to add 3 seconds delay for each element that I'm rendering on array.map
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
const delay = 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]). Appreciated any help.
Share Improve this question asked Aug 27, 2020 at 14:50 maxrojasmaxrojas 1811 gold badge3 silver badges8 bronze badges3 Answers
Reset to default 5You 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. React will then reconcile the DOM and render an extra element every second.
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 - 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
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)
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742243775a4407391.html
评论列表(0条)