简体   繁体   English

使用无限循环在 UseEffect 中反应钩子函数

[英]React Hook Function in UseEffect with infinite loop

I am trying to call a hook in my App.js file using a hook.我正在尝试使用钩子在我的 App.js 文件中调用一个钩子。 All the logic works, but I'm getting a warning error in console "React Hook useEffect has a missing dependency: 'initAuth'."所有逻辑都有效,但我在控制台中收到警告错误"React Hook useEffect has a missing dependency: 'initAuth'." I know there are a lot of issues on this ,but I'm not sure if this is related to the hook or the complexity I am doing at the high level of my app.我知道这有很多问题,但我不确定这是否与钩子或我在应用程序的高层所做的复杂性有关。 The intent is to use the "initAuth" function to look at my local storage and get my user token, name, etc... I only want this on a hard page refresh, so it should only run once.目的是使用“initAuth”函数来查看我的本地存储并获取我的用户令牌、名称等......我只希望在硬页面刷新时使用它,所以它应该只运行一次。

If I add initAuth (the function) or the authObject ( object), I get infinite loops.如果我添加 initAuth(函数)或 authObject(对象),我会得到无限循环。

function App() {

  const { initAuth, authObject } = useAuth();

  useEffect(() => {
    initAuth();
  }, []);
// this throws the warning.  I need to add dependency
}

If you only want this effect to run once when the component first loads, then you can ignore the warning.如果您只希望此效果在组件首次加载时运行一次,则可以忽略该警告。 You can disable the warning so it doesn't keep showing up in the console with the following:您可以禁用警告,使其不会继续显示在控制台中,如下所示:

useEffect(() => {
  initAuth();

// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

This is how I would implement this hook :这就是我将如何实现这个钩子:

function App() {

  const { initialized, authObject, initAuth } = useAuth();

  useEffect(() => {
    if (!initialized) {
       initAuth();
    }
  }, [initialized, initAuth]);
  
  ...
}

Or, better yet :或者,更好的是:

function App() {

  const authObject = useAuth();   // let useAuth initialize itself

 
  ...
}

Typically, useAuth seems to be a multi-purpose hook, being used by various components, so it makes no sense to allow multiple components to call initAuth ;通常, useAuth似乎是一个多用途的钩子,被各种组件使用,因此允许多个组件调用initAuth是没有意义的; the hook should only return the current state.钩子应该只返回当前状态。

Preferably, you should implement that hook with a context最好,您应该使用上下文实现该钩子

function App() {

  return (
    <AuthProvider>
      <AppContent />
    </AuthProvider>
  );
}

function AppContent() {
  const authObject = useAuth();

  ...

}

The contract, therefore, goes to the AuthProvider , and notifies every component using useAuth on state changes.因此,合约转到AuthProvider ,并在状态更改时使用useAuth通知每个组件。

Thanks to Yanick's comment, this is how I initiated to provider to set my authorization:感谢 Yanick 的评论,这就是我向提供商发起设置我的授权的方式:

import React, { useState, useEffect } from "react";

const AuthContext = React.createContext([{}, () => {}]);

const AuthContextProvider = (props) => {
  const [state, setState] = useState({ isLoggedIn: false });

  useEffect(() => {
    var auth = localStorage.getItem("authObject");

    if (auth) {
      setState({ isLoggedIn: true, authObject: auth });
    } else {
      setState({ isLoggedIn: false });
    }
  }, []);
  return (
    <AuthContext.Provider value={[state, setState]}>
      {props.children}
    </AuthContext.Provider>
  );
};

export { AuthContext, AuthContextProvider };

And my App.js simply uses the ContextProvider, no need to run useEffect anymore on App.js.而我的 App.js 只使用了 ContextProvider,不再需要在 App.js 上运行 useEffect。

      <AuthContextProvider>
        <ThemeProvider theme={darkState ? dark() : light()}>
          <CssBaseline>
            <BrowserRouter>
              
            //...app.js stuff    
               
            </BrowserRouter>
          </CssBaseline>
        </ThemeProvider>
      </AuthContextProvider>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM