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
CodePudding user response:
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.
CodePudding user response:
If you want put cleanup in useEffect just do it. Activate useEffect when some boolean = true and with help onClick change it.