我正在练习 AWS 的 Cognito。对于前端,我使用 React,而对于路由,我使用 React-router-dom。对于 Cognito 验证,我使用 amazon-cognito-identity-js 包。我的 Congito signin
、signup
和 confirmation
逻辑工作正常。我做了一个辅助函数来验证 Congnito。并在不同的组件中重用它。我将导航栏分成两个部分。从Congnito当前用户我制作了一个回调函数并在useEffect中使用它,并且依赖项放置了回调函数,默认情况下getAuthenticatedUser
为null。我添加了获取数据的条件,如果 getAuthenticatedUser
然后重定向到 signin
和 signup
页面。由于这种情况,我收到错误:Can't perform a React state update on an unmounted component.....
。此外,当我登录时,它不会更改导航栏名称,我必须刷新浏览器才能看到更改。我在 codesandbox 中分享了我的代码。
这是我的辅助函数
import React, { useState, useCallback, useEffect, useMemo } from 'react';
import { CognitoUserPool } from 'amazon-cognito-identity-js';
const Pool_Data = {
UserPoolId: 'us-east-1_IEyFfUupx',
ClientId: '63fc9g5c3g9vhqdalrv9eqhoa2',
};
export default function useHandler() {
const [state, setstate] = useState({
loading: false,
isAuthenticated: false
})
const { loading, isAuthenticated } = state;
const userPool = new CognitoUserPool(Pool_Data)
const getAuthenticatedUser = useCallback(() => {
return userPool.getCurrentUser();
},
[],
);
console.log(getAuthenticatedUser());
useEffect(() => {
getAuthenticatedUser()
}, [getAuthenticatedUser])
const signOut = () => {
return userPool.getCurrentUser()?.signOut()
}
console.log(getAuthenticatedUser());
return {
loading,
isAuthenticated,
userPool,
getAuthenticatedUser,
signOut
}
};
这是我的导航
import React, { useEffect } from "react";
import { Link } from "react-router-dom";
import SigninLinks from './SigninLinks';
import SignoutLinks from './SignoutLinks';
import useHandlder from '../configHandler/useHandler';
const Nav = () => {
const { getAuthenticatedUser } = useHandlder();
const Links = getAuthenticatedUser() ? <SigninLinks /> : <SignoutLinks />
return (
<nav className="nav-wrapper grey darken-3">
<div className="container">
<h2 className="brand-logo">Logo</h2>
{
Links
}
</div>
</nav>
);
};
export default Nav;
这是显示数据和获取错误信息的主屏幕
import React, { useState, useEffect } from "react";
import { api } from './api';
import useHandlder from './configHandler/useHandler'
import { Redirect } from 'react-router-dom';
const Home = () => {
const [state, setstate] = useState([]);
const { getAuthenticatedUser } = useHandlder();
useEffect(() => {
fetchData()
}, [])
const fetchData = async () => {
const response = await fetch(`https://jsonplaceholder.typicode.com/posts`);
const data = await response.json();
setstate(data)
}
return getAuthenticatedUser() === null ? <Redirect to="/signin" /> : //In here is the //error happening.
<div className="row">
<h1>hello welcome to home</h1>
{
state?.map((i: string, id: number) => <h1 key={id}>{i.title}</h1>)
}
</div>
};
export default Home;
答案 0 :(得分:1)
问题是您的应用在主 ("/"
) 路径上启动并呈现 Home
组件。 Home
在挂载时发起 GET 请求并检查经过身份验证的用户,如果没有,则重定向到您的“/signin”路由。
fetch
是异步,因此当发生重定向时,GET 请求正在解析 Home
已卸载并尝试更新具有响应数据的本地状态,但不能。
您需要使用 Abort Controller 取消进行中的请求。如果组件卸载,效果清除功能会取消获取请求。在 Home
中更新 useEffect
钩子以创建要在清理函数中使用的 AbortController
和 signal
。
useEffect(() => {
const controller = new AbortController(); // <-- create controller
const { signal } = controller; // <-- get signal for request
const fetchData = async () => {
const response = await fetch(
`https://jsonplaceholder.typicode.com/posts`,
{ signal } // <-- pass signal with options
);
const data = await response.json();
setstate(data);
};
fetchData();
return () => controller.abort(); // <-- return cleanup function to abort
}, []);