useReducer возвращает обещание вместо обновленного состояния

Мой редуктор:

export const initialUserState = {
    username: '',
    address: '',
    token: '',
    address: '',
    loggedIn: false,
    loaded: false,
};

export const userReducer = async (state, action) => {
    try {
        switch (action.type) {
            case 'LOAD':
                try {
                    const value = JSON.parse(await AsyncStorage.getItem('user_info'));
                    const newState = { ...state, ...value, loggedIn: true, loaded: true };
                    console.log('New State:', newState);

                    if (value !== null) {
                        return newState;
                    }
                } catch (error) {
                    return { ...state, loaded: true };
                }
                break;
            default:
                return state;
        }
    } catch (error) {
        console.log(error);
        return state;
    }
};

Мой App.js:

import { userReducer, initialUserState } from './reducer';

const App = () => {
    const [user, dispatch] = useReducer(userReducer, initialUserState);

    useEffect(() => {
        dispatch({ type: 'LOAD', ready: setReady });
    }, []);

    useEffect(() => {
        console.log('state user:', user);
    }, [user]);
}

export default App;

Что происходит, так это то, что в App.js после вызова второго useEffect состояние обновляется, и пользователь возвращает обещание. Обещание имеет несколько свойств, внутри одного из которых указано правильное состояние, которое оно должно было вернуть. Разве это не должно вернуть состояние? Я делаю что-то неправильно?

В двух словах:

1) Приложение запускается

2) useEffect вызывает первый раз и имеет правильное начальное состояние

3) Я вызываю действие ЗАГРУЗИТЬ, которое обновит состояние

4) useEffect вызывается второй раз. На этот раз он возвращает обещание, и я думаю, он должен возвращать только обновленное состояние магазина?

2 ответа

Решение

Похоже, функция, которую вы передаете useReducer является async. Всеasyncфункции возвращают обещание. Вам нужно будетawait или используйте .thenсинтаксис для получения значения из обещания. Это не обещание с первого раза, потому что оно возвращает начальное состояние. Надеюсь, это поможет!

Он возвращает обещание, потому что редуктор является асинхронной функцией, и это из-за ожидаемого вызова AsyncStorage:

const value = JSON.parse(await AsyncStorage.getItem('user_info'));

Вы должны переместить извлечение хранилища в ловушку эффекта, а затем dispatch результат принятого / отклоненного обещания.

Еще одна причина переместить извлечение данных заключается в том, что редукторы должны быть чистыми функциями (это ссылка на документы Redux, но идея все еще применима к редукторам React). Единственный источник данных, который должен иметь редуктор, - это егоstate а также actionпараметры. Это позволяет детерминированное поведение по отношению к этим параметрам; с одинаковыми аргументами отдельные вызовы редуктора всегда должны возвращать один и тот же результат.

Другие вопросы по тегам