javascript - How to use setTimeout within a .map() in reactJS - Stack Overflow

I have an array of players which I map through. The user is constantly adding new players to this array

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
Add a ment  | 

2 Answers 2

Reset to default 6

You 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.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744318626a4568303.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信