代码之家  ›  专栏  ›  技术社区  ›  Ben_Sven_Ten

在下一步中暴露每个组件。js应用程序到页面加载上的自定义挂钩

  •  0
  • Ben_Sven_Ten  · 技术社区  · 3 年前

    在我的 Next.js 在应用程序中,我有一个react钩子,可以获取当前经过身份验证的用户,并将其设置为一个全局状态。我想在页面加载时运行这个钩子一次,但我想让它暴露给应用程序中的每个组件

    import { useState, useEffect } from 'react';
    import { useQuery } from '@apollo/client';
    import { GET_AUTHED_USER } from '../utils/queries';
    import { useAppContext } from '../context';
    
    export const getCurrentUser = () => {
        const [isCompleted, setIsCompleted] = useState(false)
    
        const [state, setState] = useAppContext()
    
        const { data: authedUserData } = useQuery(GET_AUTHED_USER, {
            onCompleted: () => setIsCompleted(true)
        });
    
        useEffect(() => {
            Router.push('/home')
            if (isCompleted) {
                setState({
                    currentUser: authedUserData?.getAuthedUser,
                    isAuthed: true,
                });
            }
        }, [isCompleted]);
    
        return [state, setState];
    

    _ 应用程序。js

    import '../styles/reset.css'
    import { AppWrapper } from '../context'
    import { getCurrentUser } from '../hooks';
    
    
    function MyApp({ Component, pageProps }) {
      const [state] = getCurrentUser()
    
      console.log(state) // TypeError: Invalid attempt to destructure non-iterable instance.
    
      return (
        <AppWrapper>
          <Component {...pageProps} />
        </AppWrapper>
      )
    }
    
    
    export default MyApp
    

    钩子在里面确实有用 pages/index.js 但这意味着我只能在 / 端点被击中。

    <AppWrapper/> 是最初定义所有值的地方

    import { createContext, useContext, useState } from 'react';
    import { ApolloClient, InMemoryCache, ApolloProvider, createHttpLink } from '@apollo/client';
    import { setContext } from '@apollo/client/link/context';
    import { getCookie } from '../utils/functions';
    
    
    const AppContext = createContext();
    
    export function AppWrapper({ children }) {
    
      const URI = 'http://localhost:5000/graphql';
    
      const [state, setState] = useState({
        currentUser: null,
        isAuthed: false,
      });
    
      const httpLink = createHttpLink({
        uri: URI,
      });
    
      const authLink = setContext((_, { headers }) => {
        // get the authentication token from local storage if it exists
        const token = getCookie('JWT');
        // return the headers to the context so httpLink can read them
        return {
          headers: {
            ...headers,
            authorization: token ? token : '',
          }
        }
      });
    
      const client = new ApolloClient({
        cache: new InMemoryCache(),
        link: authLink.concat(httpLink)
      });
    
    
      return (
        <AppContext.Provider value={[state, setState]}>
          <ApolloProvider client={client}>
            {children}
          </ApolloProvider>
        </AppContext.Provider>
      );
    }
    
    
    export function useAppContext() {
      return useContext(AppContext);
    }
    
    
    1 回复  |  直到 3 年前
        1
  •  1
  •   windmaomao    3 年前

    有趣的问题是,你想在每次点击浏览器时只加载这部分代码一次吗?

    那么位置就对了。 NextJs 确保当你点击一个独特的浏览器时,它会运行 _app.js ,但只有一次,之后它将进入单页应用程序模式。

    在上述事实之后,实际上一段代码是否只运行一次、两次或多次主要取决于它检测到“更改”的次数。

      useEffect(() => {
         // run
      }, [condition])
    

    如果条件发生变化,它将再次运行。然而,如果条件没有改变,但整个部件被重新安装,它将再次运行。你必须在这里考虑这两个事实。

    简而言之,如果每次路线改变都要运行它,那么 condition === route.name .一条建议,首先尝试使用单页应用程序,然后使用独特的功能 nextJS ,否则就很难找到答案。