我碰到了AsyncStorage
的一种奇怪的行为,我无法绕过头脑,并且会感谢任何能够向我解释幕后发生的事情(即失败案例和原因)
这是我正在处理的代码:
componentDidMount() {
let _this = this;
AsyncStorage.getItem('token', (err, data) => {
setTimeout(() => {
if(data !== null){
this.setState({isReady: true, isLoggedIn: true});
store.dispatch({type: t.LOGGED_IN, token: data});
}
else{
this.setState({isReady: true, isLoggedIn: false})
store.dispatch({type: t.LOGGED_OUT});
}
}, 3000)
console.log(err);
});
}
正如您所看到的,我正在根据文档将callback
函数传递给getItem()
,这基本上告诉我用户之前是否已登录并且之后没有注销(即令牌仍然存在于某处的设备/应用程序中)。
这段代码第一次成功,检索了我通过reducer存储的旧令牌:
export default function authReducer(state = initialState, action)
{
switch (action.type) {
case t.LOGGED_IN:{
AsyncStorage.setItem('token', action.token);
return Object.assign({}, state, { isLoggedIn: true, token: action.token });
}
case t.LOGGED_OUT:{
AsyncStorage.removeItem('token');
return Object.assign({}, state, {isLoggedIn: false, token: null});
}
default:
return state;
}
}
然而,在我第二次重新加载应用时,即使在我尝试一次又一次登录后,AsyncStorage
也始终无法检索数据。
我也尝试了AsyncStorage
次调用的变体,即使用await
,.then
加.catch
,但它们都会导致相同的结果。
我的问题是:
在失败的情况下,我认为getItem()
仍会调用我传递的回调函数,因为参数列表上有error
。但是,我的console.log从未在上述情况下运行。我期待一些我不应该在这里的东西吗?
为什么它只会在第二次失败?是否存在多次调用setItem()
同一个密钥而不删除它会导致存储失败的情况? (我确信第一次尝试是成功的,因为我从异步存储打印了检索到的令牌)
这是否与我从Expo加载我的应用并使用CRNA初始化应用程序这一事实有关?这会以某种方式使asyncStorage持久性质量不同吗?
答案 0 :(得分:0)
所以问题现在解决了,感谢我的一位经验丰富的程序员朋友。
事实证明我的错误是我把AsyncStorage.setItem()
调用放在reducer中,他说自然是deterministic
。
我在调度之前将调用移动到该类的actions.js
,并且它有效!
所以而不是
export default function authReducer(state = initialState, action)
{
switch (action.type) {
case t.LOGGED_IN:{
AsyncStorage.setItem('token', action.token);
return Object.assign({}, state, { isLoggedIn: true, token: action.token });
}
case t.LOGGED_OUT:{
AsyncStorage.removeItem('token');
return Object.assign({}, state, {isLoggedIn: false, token: null});
}
default:
return state;
}
}
我做了
export default function authReducer(state = initialState, action)
{
switch (action.type) {
case t.LOGGED_IN:{
return Object.assign({}, state, { isLoggedIn: true, token: action.token });
}
case t.LOGGED_OUT:{
return Object.assign({}, state, {isLoggedIn: false, token: null});
}
default:
return state;
}
}
加上
export function login(data, successCB, errorCB) {
return (dispatch) => {
api.login(data, function (success, data, error) {
if (success && data.exists) {
AsyncStorage.setItem('token', data.token); //NOTE THIS
dispatch({type: t.LOGGED_IN, token: data.token});
successCB(data);
}else if (error) errorCB(error)
});
};
}
export function signOut(successCB, errorCB){
return (dispatch) => {
AsyncStorage.removeItem('token'); //NOTE THIS
dispatch({type: t.LOGGED_OUT});
successCB();
}
}
但我的问题仍然是persists
(原谅双关语),"为什么这个简单的修改有效?我是否理解reducers
和dispatchers
错误的机制?"
此外,deterministic
对Async
来电不兼容有何意义?
如果有人能向我解释那个很棒的概念! :d
答案 1 :(得分:0)
减速器必须没有副作用,因为它是纯粹的功能。
正如docs
中所述它们必须是纯函数 - 函数,它们返回给定输入的完全相同的输出。他们也应该免费副作用。
副作用 - 当程序从其范围外部更改变量时
更好的方法是使用redux-saga,,就像你的副作用模型的单独线程。