ГлавнаяБлогErrors / FixesПочему React отображает промежуточное состояние между двумя вызовами setState? [дублированная вопрос]
Errors / Fixes5 сентября 2026 г.3 мин

Почему React отображает промежуточное состояние между двумя вызовами setState? [дублированная вопрос]

Почему React отображает промежуточное состояние между вызовами setState? ## Введение В процессе разработки пользовательского интерфейса часто возникают ситуации, когда неожиданные промежуточные состояния могут появляться между вызовами `setState` в React....

Почему React отображает промежуточное состояние между двумя вызовами setState? [дублированная вопрос]
Почему React отображает промежуточное состояние между двумя вызовами setState? [дублированная вопрос] - image 2

Почему React отображает промежуточное состояние между вызовами setState?

Введение

В процессе разработки пользовательского интерфейса часто возникают ситуации, когда неожиданные промежуточные состояния могут появляться между вызовами setState в React. Это может быть особенно заметно на страницах, где пользователь выполняет несколько действий подряд. В данной статье рассмотрим пример из реальной разработки, связанной с поиском адреса и отображением результатов.

Пример реализации

Рассмотрим страницу AddressSearch, которая позволяет пользователю вводить адрес, получать предложенные варианты от Google Maps API и отображать результаты на экране. Важные части кода представлены ниже:

export const useSystemAddressStrategy = ({ companyId, gMaps, initialAddress }: SystemAddressStrategyOptions): StrategyResult => {
    // ----- Address
    const [addressParams, setAddressParams] = useState<AdvancedSearchAddressPayload & { formattedAddress: string }>(convertToAddressPayload(initialAddress));

    // ----- Page
    const [page, setPage] = useState<number>(0);

    // ----- Sort Direction
    const [sortDirection, setSortDirection] = useState<SortDirection>(SortDirection.ASC);
};

Основные действия

  1. Изменение адреса: При изменении адреса все данные на UI очищаются, происходит новый запрос с новым адресом, и данные отображаются.
  2. Изменение сортировки: При изменении направления сортировки все данные на UI также очищаются, происходит новый запрос с новым направлением сортировки, и данные отображаются.
  3. Прокрутка до конца страницы: При прокрутке до конца страницы происходит вызов нового API-запроса с увеличенным номером страницы, и новые данные добавляются к существующим.

Проблема промежуточного состояния

Проблема заключается в том, что между вызовами setState может появляться промежуточное состояние, которое не соответствует ни одному из ожидаемых состояний. Это происходит из-за асинхронности вызовов API и обновления состояния компонента.

Как это работает

Когда пользователь выполняет действие, например, меняет адрес, React обновляет состояние и рендерит компонент. Однако, до тех пор, пока новый запрос API не завершится и не обновит состояние, промежуточное состояние может быть видно на экране.

Пример

Предположим, пользователь вводит новый адрес. React обновляет состояние и рендерит компонент с очищенным UI. После этого происходит API-запрос. До завершения запроса, пользователь может видеть промежуточное состояние, где часть данных уже обновилась, а часть еще нет.

Решение проблемы

Чтобы избежать промежуточного состояния, можно использовать различные подходы:

1. Использование флагов загрузки

Добавьте флаг загрузки для каждого действия, чтобы отображать состояние загрузки вместо промежуточного состояния.

const [isLoading, setIsLoading] = useState(false);

useEffect(() => {
    if (isLoading) {
        return;
    }

    setIsLoading(true);

    fetchNewData()
        .then(data => {
            // Обновление состояния после получения данных
            setPage(0);
            setAddressParams(convertToAddressPayload(newAddress));
        })
        .finally(() => setIsLoading(false));
}, [isLoading, newAddress]);

2. Заморозка UI

Заморозьте UI во время выполнения запроса и разморозьте его после получения данных.

const handleAddressChange = (newAddress) => {
    setIsLoading(true);
    fetchNewData(newAddress)
        .then(data => {
            setPage(0);
            setAddressParams(convertToAddressPayload(newAddress));
        })
        .finally(() => setIsLoading(false));
};

3. Управление состоянием внутри функций

Используйте функциональные методы для управления состоянием внутри обработчиков событий.

const handleAddressChange = (newAddress) => {
    const fetchData = async () => {
        setIsLoading(true);
        await fetchNewData(newAddress);
        setPage(0);
        setAddressParams(convertToAddressPayload(newAddress));
        setIsLoading(false);
    };

    fetchData();
};

Практические советы

  1. Используйте useEffect для управления состоянием после выполнения API-запроса.
  2. Добавьте флаги загрузки для отображения состояния загрузки.
  3. Замораживайте UI во время выполнения запросов.
  4. Используйте функциональные методы для управления состоянием.

Заключение

Промежуточное состояние между вызовами setState может вызывать проблемы в приложениях React. Использование флагов загрузки, заморозки UI и функциональных методов помогут управлять состоянием более эффективно и избежать нежелательных промежуточных состояний.