自定义挂钩,以等待useEffect挂钩的回调

时间:2020-02-07 12:22:34

标签: javascript reactjs

我有一个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;

现在它进入无限循环。

1 个答案:

答案 0 :(得分:2)

因此,首先您必须按照React Documentation中的建议将自定义钩子重命名为 useLoadUserProfile ,以便React能够自动检查是否违反了钩子规则。无限循环是由依赖数组中包含 loading error 状态引起的。 在这种情况下,只要您调用'setMyState',就 setLoading setError

  1. React再次重新运行您的自定义挂钩,并返回更新的正在加载错误状态
  2. 然后再次运行useEffect挂钩,并调用 setLoading setError ,这将导致React再次运行您的函数....从而发生无限循环。

因此要解决此问题,必须从依赖项数组中删除 loading error 状态。经验法则是:
如果指定了依赖项数组,则组件中内部所有由效果使用的值都必须存在。包括道具,状态,功能-组件中的任何内容。 ,即永远不要依赖于依赖项。

就您而言,您的useEffect挂钩甚至不取决于您的正在加载错误状态。因此,它们首先不应该在依赖项数组中!