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
параметры. Это позволяет детерминированное поведение по отношению к этим параметрам; с одинаковыми аргументами отдельные вызовы редуктора всегда должны возвращать один и тот же результат.