简体   繁体   中英

React: how to asynchronously and sequentially remove elements from array state?

I'm having hard time finding a way to solve quite simple problem in React:

import React, { useState } from 'react';
import './style.css';

const removeTodoFromDb = (todo) =>
  new Promise((resolve) => {
    setTimeout(resolve, 1000);
  });

export default function App() {
  const [todos, setTodos] = useState(['sleep', 'work', 'eat', 'play']);

  const cleanup = async () => {
    console.log('cleanup()');
    if (todos.length) {
      console.log('1', todos.join('|'));
      todos[0] = todos[0] + '*';
      setTodos((t) => todos.slice());
      await removeTodoFromDb(todos.shift());
      setTodos((t) => todos.slice());
      cleanup();
      console.log('2', todos.join('|'));
    }
  };

  return (
    <>
      {todos.map((t, i) => (
        <div key={i}>{t}</div>
      ))}
      <button onClick={() => cleanup()}>Clean up</button>
    </>
  );
}

StackBlitz url: https://stackblitz.com/edit/react-aa6wde

I know todos , and setTodos loose references, but I cannot put cleanup() function into the useEffect block as it won't be exposed to the DOM.

What is the proper pattern for actions like this?

Thanks

If I understand correctly, you want to remove all elements of an array one after another, right?

If so, here's how I would write the cleanup function:

const cleanup = async () => {
  if (!todos.length) return

  // Use Promise.all to call removeTodoFromDb for ALL todos at the SAME time
  await Promise.all(todos.map(todo => removeTodoFromDb(todo))
  setTodos([])
};

Not sure you mean by this:

I know todos, and setTodos loose references, but I cannot put cleanup() function into the useEffect block as it won't be exposed to the DOM.

If you want put cleanup in useEffect just do it. Activate useEffect when some boolean = true and with help onClick change it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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