如何避免由于 redux 状态的 redux store update/propagation 到连接组件的延迟而导致的重复操作分派?
How do I avoid duplicate action dispatches caused by to a delay in redux store update/propagation of redux state to connected components?
我正在开发一个使用 React-Router 和 Redux 的 React 应用程序。
这个应用程序有一些需要身份验证的路由,在这种情况下,我将用户重定向到登录页面,如下所示。
return <Redirect
to={{
pathname: '/login',
search: `?ret=${encodeURIComponent(location.pathname)}`
}}
登录页面使用登录组件呈现,该组件连接到 redux 存储并检查布尔值 isSignedIn
。当 isSignedIn === true
时,我将用户重定向到 ret
查询参数中指定的路径。相关代码如下。
const Login = (props) => {
if (!props.isSignedIn) {
// show a message and CTA asking the user to log in
}
const queryParams = qs.parse(props.location.search, { ignoreQueryPrefix: true });
const ret = queryParams.ret || '/';
return <Redirect to={ret} />
}
我在应用程序中使用 google oAuth2,在用户通过 Google 登录后,我发送一个 SIGN_IN 操作,将 isSignedIn
更新为 true
。 oAuth 流程由 GoogleAuth 组件处理,该组件会在每次呈现页面时检查用户是否已登录,并且还会处理登录 in/sign 退出点击事件。此组件呈现在应用程序的每个页面上。
class GoogleAuth extends React.Component {
componentDidMount() {
window.gapi.load('client:auth2', () => {
window.gapi.client.init({
clientId: 'someclientid',
scope: 'email'
}).then(() => {
this.auth = window.gapi.auth2.getAuthInstance();
// initial check to see if user is signed in
this.onAuthChange(this.auth.isSignedIn.get());
// listens for change in google oAuth status
this.auth.isSignedIn.listen(this.onAuthChange);
})
});
};
onAuthChange = async (isGoogleSignedIn) => {
if (!this.props.isSignedIn && isGoogleSignedIn){
await this.props.signIn(this.auth.currentUser.get().getId());
} else if (this.props.isSignedIn && !isGoogleSignedIn) {
await this.props.signOut();
}
}
handleSignIn = () => {
this.auth.signIn();
}
handleSignOut = () => {
this.auth.signOut();
}
我面临的问题是,当我从“/login”页面登录并重定向时,SIGN_IN 操作(通过调用 this.props.signIn()
调度)被多次调用.
重定向似乎发生在 redux 存储正确更新 isSignedIn
的值之前,这导致了重复的 SIGN_IN 动作调度。
我该如何防止这种情况发生?我考虑过在重定向之前添加一个短暂的延迟,但我不确定这是正确的方法。
编辑:
我发现发生这种情况是因为我在登录页面上渲染了两次 GoogleAuth 组件(一次在 header 中,一次在页面本身上)。这导致动作被分派两次。两个 GoogleAuth 组件都检测到身份验证状态的变化,因此都派发了 SIGN_IN 操作。至少在这种情况下,redux 存储数据到连接组件的传播没有延迟。
好的,明白了。
我在登录页面上渲染了两次 GoogleAuth 组件 - 一次在 header 中,一次在主要内容中。这就是该操作被分派两次的原因。
两个 GoogleAuth 组件都检测到身份验证状态的变化,因此都派发了 SIGN_IN 操作。
我正在开发一个使用 React-Router 和 Redux 的 React 应用程序。
这个应用程序有一些需要身份验证的路由,在这种情况下,我将用户重定向到登录页面,如下所示。
return <Redirect
to={{
pathname: '/login',
search: `?ret=${encodeURIComponent(location.pathname)}`
}}
登录页面使用登录组件呈现,该组件连接到 redux 存储并检查布尔值 isSignedIn
。当 isSignedIn === true
时,我将用户重定向到 ret
查询参数中指定的路径。相关代码如下。
const Login = (props) => {
if (!props.isSignedIn) {
// show a message and CTA asking the user to log in
}
const queryParams = qs.parse(props.location.search, { ignoreQueryPrefix: true });
const ret = queryParams.ret || '/';
return <Redirect to={ret} />
}
我在应用程序中使用 google oAuth2,在用户通过 Google 登录后,我发送一个 SIGN_IN 操作,将 isSignedIn
更新为 true
。 oAuth 流程由 GoogleAuth 组件处理,该组件会在每次呈现页面时检查用户是否已登录,并且还会处理登录 in/sign 退出点击事件。此组件呈现在应用程序的每个页面上。
class GoogleAuth extends React.Component {
componentDidMount() {
window.gapi.load('client:auth2', () => {
window.gapi.client.init({
clientId: 'someclientid',
scope: 'email'
}).then(() => {
this.auth = window.gapi.auth2.getAuthInstance();
// initial check to see if user is signed in
this.onAuthChange(this.auth.isSignedIn.get());
// listens for change in google oAuth status
this.auth.isSignedIn.listen(this.onAuthChange);
})
});
};
onAuthChange = async (isGoogleSignedIn) => {
if (!this.props.isSignedIn && isGoogleSignedIn){
await this.props.signIn(this.auth.currentUser.get().getId());
} else if (this.props.isSignedIn && !isGoogleSignedIn) {
await this.props.signOut();
}
}
handleSignIn = () => {
this.auth.signIn();
}
handleSignOut = () => {
this.auth.signOut();
}
我面临的问题是,当我从“/login”页面登录并重定向时,SIGN_IN 操作(通过调用 this.props.signIn()
调度)被多次调用.
重定向似乎发生在 redux 存储正确更新 isSignedIn
的值之前,这导致了重复的 SIGN_IN 动作调度。
我该如何防止这种情况发生?我考虑过在重定向之前添加一个短暂的延迟,但我不确定这是正确的方法。
编辑: 我发现发生这种情况是因为我在登录页面上渲染了两次 GoogleAuth 组件(一次在 header 中,一次在页面本身上)。这导致动作被分派两次。两个 GoogleAuth 组件都检测到身份验证状态的变化,因此都派发了 SIGN_IN 操作。至少在这种情况下,redux 存储数据到连接组件的传播没有延迟。
好的,明白了。
我在登录页面上渲染了两次 GoogleAuth 组件 - 一次在 header 中,一次在主要内容中。这就是该操作被分派两次的原因。
两个 GoogleAuth 组件都检测到身份验证状态的变化,因此都派发了 SIGN_IN 操作。