Skip to content

Commit

Permalink
What happens when useEffect contains a async method with multiple set…
Browse files Browse the repository at this point in the history
…State?
  • Loading branch information
Nikoms committed Jan 31, 2021
1 parent e53c81e commit 3a95205
Showing 1 changed file with 19 additions and 2 deletions.
21 changes: 19 additions & 2 deletions src/Todo/TodoList.js
Expand Up @@ -18,18 +18,35 @@ const fetchTodosFromApi = async () => {
const TodoList = () => {
const [todos, setTodoList] = useState([]);
useEffect(function callApi() {
//1. Imagine that we are calling an api to get todos
fetchTodosFromApi().then(list => setTodoList(list));
}, []);

//2. And we have a state for 2 counter
const [ongoingCount, setOngoingCount] = useState(0);
const [doneCount, setDoneCount] = useState(0);

// 3. But what if the setter are in a async method ?
useEffect(function refreshCounters() {
setDoneCount(todos.filter(t => t.done).length);
setOngoingCount(todos.filter(t => !t.done).length);
(async () => {
new Promise(resolve => setTimeout(() => {
setDoneCount(todos.filter(t => t.done).length);
setOngoingCount(todos.filter(t => !t.done).length);
resolve();
}, 1));
})();
}, [todos]);

//4. See how many render ?
console.log('render with', {total: todos.length, ongoingCount, doneCount});
// When I set one of the todos as "done", it re-renders 3 times
// render with { total: 5, ongoingCount: 5, doneCount: 0 } ==> when setTodoList is called
// render with { total: 5, ongoingCount: 5, doneCount: 1 } ==> when setDoneCount is called
// render with { total: 5, ongoingCount: 4, doneCount: 1 } ==> when setOngoingCount is called

//2 conclusions:
// - We still have too many render!
// - Once you are outside the "useEffect" thread, you have as many render as "setter"

const addEmptyTodo = () => setTodoList([createTodo('Relax! Edition will come...', false), ...todos]);
const markAsDone = (index) => setTodoList([...todos.slice(0, index), {
Expand Down

0 comments on commit 3a95205

Please sign in to comment.