繁体   English   中英

Nextjs TypeScript useContext 通过页面

[英]Nextjs TypeScript useContext through the pages


编辑:

我没有使用

import Link from 'next/link';

在我的Header.tsx组件中。

现在它起作用了。


不知道我在这里做错了什么。 我尝试创建仅流经页面的全局状态(以指示用户是否已登录),并尝试使用 react 的钩子 useContext 来实现。

它不像我想让它工作的方式工作。 当我toggleLogged并转到另一个页面时,上下文具有默认值而不是更改的值。 我认为我面临的问题是一些非常小的或我无法看到的基本问题。

这是我的UserContext.ts文件的外观:

import { createContext, useContext } from 'react';

type userContextType = {
  isLogged: boolean;
  toggleLogged: () => void;
};

const userContextDefault: userContextType = {
  isLogged: false,
  toggleLogged: () => {},
};

export const UserContext = createContext(userContextDefault);

export function useUserContext() {
  return useContext(UserContext);
}

这是我的Layout.tsx

import React, { useState } from 'react';
import Header from './Header';

const Layout = (props: any) => {
  const { children } = props;

  return (
    <div className='container'>
      <Header />
      {children}
    </div>
  );
};

export default Layout;

最后这里是我的_app.tsx

import type { AppContext, AppProps } from 'next/app';
import Layout from '../components/Layout';
import { useState } from 'react';
import { UserContext } from '../components/UserContext';

import '../styles/globals.css';

const MyApp = ({ Component, pageProps }: AppProps) => {
  const [isLogged, setIsLogged] = useState(true);
  const toggleLogged = () => {
    setIsLogged((isLogged) => !isLogged);
  };

  return (
    <UserContext.Provider value={{ isLogged, toggleLogged }}>
      <Layout>
        <Component {...pageProps} />;
      </Layout>
    </UserContext.Provider>
  );
};

export default MyApp;

提前感谢您的任何帮助。

您需要上下文中返回提供者,然后在 _app.js 中引用该实例。

这是我的 AuthContext(作为示例)。 不用担心具体的代码,但是以我的实现为基础,您很快就会启动并运行!

import { createContext, useContext, useEffect, useState } from 'react'
import { auth } from '../firebase'

const AuthContext = createContext()

export function useAuth() {
  return useContext(AuthContext)
}

export function AuthProvider({ children }) {
  const [currentUser, setCurrentUser] = useState()
  const [loading, setLoading] = useState(true)

  function login(email, password) {
    return auth.signInWithEmailAndPassword(email, password)
  }

  function signOut() {
    return auth.signOut();
  }

  function signUp(email, password) {
    return auth.createUserWithEmailAndPassword(email, password)
  }

  function getUser() {
    return auth.currentUser
  }

  function isAdmin() {
    return auth.currentUser.getIdTokenResult()
    .then((idTokenResult) => {
      if (!!idTokenResult.claims.admin) {
        return true
      } else {
        return false
      }
    })
  }

  function isEditor() {

  }

  useEffect(() => {
    const unsubscribe = auth.onAuthStateChanged(user => {
      setCurrentUser(user)
      setLoading(false)
    })

    return unsubscribe
  }, [])

  const value = {
    currentUser,
    getUser,
    login,
    signOut,
    signUp
  }

  return (
    <AuthContext.Provider value={value}>
      { !loading && children }
    </AuthContext.Provider>
  )

}

我的 _app.js 文件:

import '../styles/globals.scss'
import { motion, AnimatePresence } from 'framer-motion'
import { useRouter } from 'next/router'
import Header from '../components/Header'
import Footer from '../components/Footer'
import { AuthProvider } from '../contexts/AuthContext'
import { CartProvider } from '../contexts/CartContext'
import { ThemeProvider } from '@material-ui/core'
import theme from '../styles/theme'


export default function App({ Component, pageProps }) {
  const router = useRouter()

  return(
    <AnimatePresence exitBeforeEnter>
      <CartProvider>
        <AuthProvider>
          <ThemeProvider theme={theme}>
            <Header />
            <motion.div key={router.pathname} className="main">
              <Component { ...pageProps } />
              <Footer />
            </motion.div>
          </ThemeProvider>
        </AuthProvider>
      </CartProvider>
    </AnimatePresence>
  )
}

暂无
暂无

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

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