_setState
- асинхронная функция. Под капотом React объединяет все мутации состояний, благодаря чему код функционального компонента будет вызван 1 раз, это называется batching
.
function ExampleComponent() {
const [count, setCount] = useState(0);
const handleClick = () => {
// Несколько вызовов `setCount` будут сгруппированы в один батч
setCount(count + 1);
setCount(count + 2);
setCount(count + 3);
};
import React, { useState, FC } from "react";
export const ExampleFuncComponent: FC = () => {
const [count, setCount] = useState(0);
const onClick0 = () => {
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
};
const onClick1 = () => {
setCount((v) => v + 1);
setCount((v) => v + 1);
setCount((v) => v + 1);
};
return (
<div>
<div>{count.toString()}</div>
<button onClick={onClick0}>
test 0
</button>
<button onClick={onClick1}>
test 1
</button>
</div>
);
};
При нажатии на test 1
счетчик увеличится на 3, а при нажатии на test 0
только на 1. Почему это происходит:
// Например count = 0
const onClick0 = () => {
// count + 1 = 0 + 1;
setCount(count + 1)
// Здесь можем ожидать, что count уже 1, но т.к. вызов setState асинхронный
// состояние еще не изменено, поэтому count по-прежнему 0
// count + 1 = 0 + 1;
setCount(count + 1)
// count + 1 = 0 + 1;
setCount(count + 1)
}
Поэтому если новое состояние опирается на предыдущее состояние, используйте функцию:
const onClick1 = () => {
setCount((v) => v + 1)
setCount((v) => v + 1)
setCount((v) => v + 1)
}