I have an array of players which I map through. The user is constantly adding new players to this array. I map through the array and return a set of elements. I'd like each player from the list to render one at a time with a 500ms interval in between. Here's the code I have so far:
export const ShowDraftedPlayers = props => {
const {
draftedPlayers,
getPlayerProfile,
teams,
draftPos,
myTeam } = props;
let playersDraftedList = draftedPlayers.map((player, index) => {
return (
<div key={index} className='drafted'>
<p style={style}>TEAM {player.teamDraftedBy} </p>
<b className='player-lastName'> {player.displayName} </b>
{player.position}
</p>
</div>
)
})
return (
<div className='draftedPlayers-container'>
{playersDraftedList}
</div>
)
}
I have an array of players which I map through. The user is constantly adding new players to this array. I map through the array and return a set of elements. I'd like each player from the list to render one at a time with a 500ms interval in between. Here's the code I have so far:
export const ShowDraftedPlayers = props => {
const {
draftedPlayers,
getPlayerProfile,
teams,
draftPos,
myTeam } = props;
let playersDraftedList = draftedPlayers.map((player, index) => {
return (
<div key={index} className='drafted'>
<p style={style}>TEAM {player.teamDraftedBy} </p>
<b className='player-lastName'> {player.displayName} </b>
{player.position}
</p>
</div>
)
})
return (
<div className='draftedPlayers-container'>
{playersDraftedList}
</div>
)
}
Share
Improve this question
asked Jun 10, 2020 at 15:56
Luiz AlmeidaLuiz Almeida
811 silver badge7 bronze badges
3
- 4 Basically, what would you do is keep a state of the shown drafted players, and create an interval that adds to the state array item from the props each time. – Gershon Papi Commented Jun 10, 2020 at 16:00
- Use animate react native – Denis Tsoi Commented Jun 10, 2020 at 16:01
- 2 You have 2 issues here, 1: setTimeout inside a map isn't really ideal, hacks like increasing the timeout values for each item is just that, a hack. 2: React doesn't work that way, you can't pausing rendering in React, like everything else that updates in React, you need to use state. – Keith Commented Jun 10, 2020 at 16:01
2 Answers
Reset to default 6You can use an effect to create an interval which updates a counter every 500ms; your render logic can then render a growing slice of the array each time.
export const ShowDraftedPlayers = props => {
const {
draftedPlayers,
getPlayerProfile,
teams,
draftPos,
myTeam
} = props;
const [count, setCount] = useState(0);
useEffect(() => {
let counter = count;
const interval = setInterval(() => {
if (counter >= draftedPlayers.length) {
clearInterval(interval);
} else {
setCount(count => count + 1);
counter++; // local variable that this closure will see
}
}, 500);
return () => clearInterval(interval);
}, [draftedPlayers]);
let playersDraftedList = draftedPlayers.slice(0, count).map((player, index) => {
return (
<div key={index} className='drafted'>
<p style={style}>TEAM {player.teamDraftedBy} </p>
<b className='player-lastName'> {player.displayName} </b>
{player.position}
</p>
</div>
)
})
return (
<div className='draftedPlayers-container'>
{playersDraftedList}
</div>
)
}
You don't. setTimeout
is asynchronous, as so is JavaScript and React. Components are rendered as soon as possible so that JavaScript can jump to do something else. The best way is to create a hook that reacts (pun intended) to some change in value, in this case props.draftedPlayers
, setTimeout
for 500ms, then add that new player to an internal players state and let the ponent renders based on it.
Here is how the ponent will reflect a change in props.draftedPlayers
with a delay of 500ms:
export const ShowDraftedPlayers = props => {
const {
draftedPlayers,
getPlayerProfile,
teams,
draftPos,
myTeam
} = props;
const [players, setPlayers] = useState([]);
// Set internal `players` state to the updated `draftedPlayers`
// only when `draftedPlayers` changes.
useEffect(() => {
const delay = setTimeout(() => {
setPlayers(draftedPlayers);
}, 500);
return () => clearTimeout(delay);
}, [draftedPlayers]);
let playersDraftedList = players.map((player, index) => {
return (
<div key={index} className='drafted'>
<p style={style}>TEAM {player.teamDraftedBy} </p>
<b className='player-lastName'> {player.displayName} </b>
{player.position}
</p>
</div>
);
};
};
Whenever draftedPlayers
prop is changed (players added or removed) from the outer context, the ponent will update its players
array after a delay of 500ms
.