почему мой React useState не обновляет мои компоненты?

Я уверен, что это просто мое непонимание React, но я пытаюсь обновить компонент после обновления состояния (что происходит асинхронно).

const [appState, setAppState] = useState({
        countries: null,
        languages: null
    })
useEffect(() => {
        const languageURL = `//localhost:8080/languages`,
              countryURL = '//localhost:8080/countries';
        axios.get(languageURL, {
            headers: {'Access-Control-Allow-Origin': '*'}
        })
            .then((langResponse) => {
                    const languages = langResponse.data.map(l => ({
                        value: l.id,
                        label: l.language + " (" + l.code + ")"
                    }))
                    setAppState({languages: languages});
                    console.log("updating languages");
                    return languages;
                }, (error) => {
                    console.log(error)
                }
            );
        axios.get(countryURL, {
            headers: {'Access-Control-Allow-Origin': '*'}
        })
            .then((countryResponse) => {
                    const countries = countryResponse.data.map(l => ({
                        value: l.id,
                        label: l.name + " (" + l.code + ")"
                    }))
                    setAppState({countries: countries});
                    console.log("updating countries");
                    return countries;
                }, (error) => {
                    console.log(error)
                }
            );
    }, [setAppState]);

Мой компонент выглядит так (у меня по одному на каждый набор объектов):

<Select
  options={appState.countries}
  isSearchable
/>

Я убедился, что данные поступают и соответствуют формату. Проблема, по-видимому, в том, что каждый компонент не отрисовывается при обновлении предоставленного объекта состояния - только один принимает изменения. Также кажется, что одно из них разрешится первым - другое пусто. Это почти противоположно этому вопросу - они обновляются немедленно, < em> до разрешения другого набора.


person end-user    schedule 04.09.2020    source источник
comment
Unlike the setState method found in class components, useState does not automatically merge update objects. You can replicate this behavior by combining the function updater form with object spread syntax: reactjs.org/docs/hooks-reference.html#usestate   -  person Aprillion    schedule 04.09.2020
comment
Что ж, если вы замените состояние на {languages: languages}, тогда у него больше не будет записи countries, и наоборот. Обычно для них используется отдельный useState, а не тот, который содержит и то, и другое.   -  person Guy Incognito    schedule 04.09.2020
comment
Отвечает ли это на ваш вопрос? Обновление и объединение объекта состояния с помощью хука React useState ()   -  person Garrett Motzner    schedule 04.09.2020
comment
useState работает немного иначе, чем обычное состояние реакции. В определенной степени использование одного объекта для нескольких значений состояния является антипаттерном. Если у вас есть отдельные жизненные циклы для разных обновлений состояния (два значения не зависят друг от друга, как они показаны здесь), проще использовать 2 разных вызова useState. В вашем случае один для языков и один для стран. Исключением может быть ситуация, когда вам нужно передать весь объект appState. В этом случае также рассмотрите шаблон редуктора.   -  person Garrett Motzner    schedule 04.09.2020
comment
См. Также: github.com/arielweinberger/react-hooks-accessor-state для другого способа использования состояния.   -  person Garrett Motzner    schedule 04.09.2020


Ответы (2)


Я думаю, вам следует разделить состояние, если вы не хотите устанавливать его вместе, я тестировал его, и у меня возникла ошибка, когда я установил его отдельно, я думаю, что лучше разделить его и написать useEffect для каждого состояния, если это требуется

person tmohammad78    schedule 04.09.2020

Хорошо, да, похоже, ответ состоит в том, чтобы создать отдельные объекты состояния и соответственно обновить каждый; фактически то, что говорили Гаррет Моцнер и tmohammad78. Я думаю, что это позволяет компонентам, зависящим от них, видеть изменение состояния дискретно. Выглядело бы это так:

const [countries, setCountries] = useState();
const [languages, setLanguages] = useState();

useEffect(() => {
    ...
    setLanguages(languages);
    ...
    setCountries(countries);
    ...
 }, [setLanguages, setCountries]);

Если бы это был Компонент большего размера, возможно, react-hooks- accessor-state будет хорошим подходом.

person end-user    schedule 04.09.2020