我有一个Web应用程序,有一个keycloack.js实例,在该实例中,我尝试使用自定义钩子在UI呈现之前获取用户配置文件。 这样做的原因是,实际的应用程序需要在UI呈现之前在localStorage中提供一些信息。
这是我尝试在App.js
组件中实现的逻辑
import React, {Suspense} from 'react';
import 'bootstrap/dist/css/bootstrap.css';
import 'appkit-react/style/appkit-react.default.css';
import PageHub from './Components/Navigation/PageHub';
import Spinner from './Components/Shared/Spinner';
import LoadUserProfile from './_helpers/hooks/loadUserProfile'
import './i18n';
function App(props) {
const [loading, error] = LoadUserProfile(props.keycloak)
console.log(props)
if(loading){
return <Spinner />
}
if(error){
console.log(error)
return <div>Error occured!!</div>
}
console.log(loading)
console.log(error)
return (
<Suspense fallback={<Spinner/>}>
<PageHub/>
</Suspense>
);
}
export default App;
和LoadUserProfile
钩看起来像这样。
import React, { useState, useEffect } from 'react';
import Spinner from '../../Components/Shared/Spinner';
function LoadUserProfile(keycloak){
const [loading, setLoading] = useState(false);
const [error, setError] = useState({});
useEffect(() =>{
setLoading(true)
keycloak.loadUserProfile().success((profile) => {
console.debug('Loaded profile ' + profile);
localStorage.setItem("firstName", keycloak.profile.firstName);
localStorage.setItem("lastName", keycloak.profile.lastName);
localStorage.setItem('GUID', keycloak.profile.attributes.guid[0])
setLoading(false)
}).error(() => {
console.error('Failed to load profile')
setLoading(false)
setError({"error": "No user found"})
}, [keycloak, loading, error]);
})
return [loading, error]
}
export default LoadUserProfile;
现在它进入无限循环。
答案 0 :(得分:2)
因此,首先您必须按照React Documentation中的建议将自定义钩子重命名为 useLoadUserProfile ,以便React能够自动检查是否违反了钩子规则。无限循环是由依赖数组中包含 loading 和 error 状态引起的。 在这种情况下,只要您调用'setMyState',就 setLoading 或 setError
因此要解决此问题,必须从依赖项数组中删除 loading 和 error 状态。经验法则是:
如果指定了依赖项数组,则组件中内部所有由效果使用的值都必须存在。包括道具,状态,功能-组件中的任何内容。 ,即永远不要依赖于依赖项。
就您而言,您的useEffect挂钩甚至不取决于您的正在加载或错误状态。因此,它们首先不应该在依赖项数组中!