React Saga - 在承诺解决之前阻止商店更新
React Saga - Prevent store update until promise resolves
嗨,我有一个关于 redux/saga/promises 的问题 - 不完全确定问题出在哪里:
//USER SERVICE
function login(username, password) {
const requestOptions = {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body:
"username=" + username + "&password=" + password + "&grant_type=password"
};
return fetch(`${Config.apiUrl}/Token`, requestOptions)
.then(handleLoginResponse)
.then(user => {
// login successful if there's a jwt token in the response
if (user.access_token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem("user", JSON.stringify(user));
}
return user;
})
.catch(error => {
return { error };
});
}
//AUTH SAGA
export function* login(action) {
const { username, password } = action.payload;
const response = userService.login(username, password);
console.log(response);
if (response.error) {
yield put({ type: actions.LOGIN_FAILURE, payload: response.error });
} else {
yield put(actions.loginUserSuccessful());
yield delay(1000);
// yield history.push("/");
}
}
//AUTH ACTIONS
export function loginUserSuccessful() {
return { type: LOGIN_SUCCESS };
}
//AUTH REDUCER
export function authentication(state = initialState, action) {
const { payload } = action;
switch (action.type) {
case actions.LOGIN_SUCCESS:
return {
loggedIn: true,
user: action.user
};
case actions.LOGIN_FAILURE:
return state;
case actions.USERS_LOGOUT:
return state;
case actions.LOGIN_TOGGLE_MODAL:
const { isLoginModalOpen } = payload;
return {
...state,
isLoginModalOpen
};
default:
return state;
}
}
我有一个登录菜单项,当用户登录时(如商店中填充的 "user" 和 "loggedIn" 所示)将与 "member" 菜单切换物品。登录表单是 header 组件的一部分。
所以当我登录后端时被调用,令牌被设置(USER SERVICE),这是通过一个传奇(AUTH SAGA)发生的。当用户登录时,将调用操作 "loginUserSuccessful" (LOGIN ACTION)。这将调用 reducer 来更新用户和 "loggedIn" (AUTH REDUCER)
的状态
问题是 "loggedIn" 被设置为 true,并且在设置 "user" object 之前更新状态。因此,当承诺最终解决时,用户已设置,但 header 未更新。所以它只有在我重新加载页面时才会获得新状态。
我注意到,出于某种原因,当从 saga 调用操作时,我可以从操作中提取 "user",即使我在调用 loginUserSuccessful 时没有手动设置它 - 我明白了来自教程,所以我不完全确定它是如何工作的 - 我还是新手。
我确定我做错了什么。但也许有人可以提供帮助?让我知道需要更多信息。
找到答案了。很明显,传奇动作将承诺附加到动作上。但这并没有立即得到解决。我需要做的就是将用户数据作为有效负载发送。然后就成功了。
嗨,我有一个关于 redux/saga/promises 的问题 - 不完全确定问题出在哪里:
//USER SERVICE
function login(username, password) {
const requestOptions = {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body:
"username=" + username + "&password=" + password + "&grant_type=password"
};
return fetch(`${Config.apiUrl}/Token`, requestOptions)
.then(handleLoginResponse)
.then(user => {
// login successful if there's a jwt token in the response
if (user.access_token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem("user", JSON.stringify(user));
}
return user;
})
.catch(error => {
return { error };
});
}
//AUTH SAGA
export function* login(action) {
const { username, password } = action.payload;
const response = userService.login(username, password);
console.log(response);
if (response.error) {
yield put({ type: actions.LOGIN_FAILURE, payload: response.error });
} else {
yield put(actions.loginUserSuccessful());
yield delay(1000);
// yield history.push("/");
}
}
//AUTH ACTIONS
export function loginUserSuccessful() {
return { type: LOGIN_SUCCESS };
}
//AUTH REDUCER
export function authentication(state = initialState, action) {
const { payload } = action;
switch (action.type) {
case actions.LOGIN_SUCCESS:
return {
loggedIn: true,
user: action.user
};
case actions.LOGIN_FAILURE:
return state;
case actions.USERS_LOGOUT:
return state;
case actions.LOGIN_TOGGLE_MODAL:
const { isLoginModalOpen } = payload;
return {
...state,
isLoginModalOpen
};
default:
return state;
}
}
我有一个登录菜单项,当用户登录时(如商店中填充的 "user" 和 "loggedIn" 所示)将与 "member" 菜单切换物品。登录表单是 header 组件的一部分。
所以当我登录后端时被调用,令牌被设置(USER SERVICE),这是通过一个传奇(AUTH SAGA)发生的。当用户登录时,将调用操作 "loginUserSuccessful" (LOGIN ACTION)。这将调用 reducer 来更新用户和 "loggedIn" (AUTH REDUCER)
的状态问题是 "loggedIn" 被设置为 true,并且在设置 "user" object 之前更新状态。因此,当承诺最终解决时,用户已设置,但 header 未更新。所以它只有在我重新加载页面时才会获得新状态。
我注意到,出于某种原因,当从 saga 调用操作时,我可以从操作中提取 "user",即使我在调用 loginUserSuccessful 时没有手动设置它 - 我明白了来自教程,所以我不完全确定它是如何工作的 - 我还是新手。
我确定我做错了什么。但也许有人可以提供帮助?让我知道需要更多信息。
找到答案了。很明显,传奇动作将承诺附加到动作上。但这并没有立即得到解决。我需要做的就是将用户数据作为有效负载发送。然后就成功了。