简体   繁体   English

Nextjs TypeScript useContext 通过页面

[英]Nextjs TypeScript useContext through the pages


Edit:编辑:

I was not using我没有使用

import Link from 'next/link';

in my Header.tsx component.在我的Header.tsx组件中。

Now it works.现在它起作用了。


Don't know what I am doing wrong right here.不知道我在这里做错了什么。 I try to make global state (to indicate if user is logged in or not) that just flows through the pages and I try to do it with react's hook useContext.我尝试创建仅流经页面的全局状态(以指示用户是否已登录),并尝试使用 react 的钩子 useContext 来实现。

It is not working like how I would like to make it work.它不像我想让它工作的方式工作。 When I toggleLogged and go to another page, the context has default value and not the changed one.当我toggleLogged并转到另一个页面时,上下文具有默认值而不是更改的值。 I think the problem I am facing is something really small or a fundemantal thing that I just can't see.我认为我面临的问题是一些非常小的或我无法看到的基本问题。

Here is how my UserContext.ts file looks:这是我的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);
}

Here is my Layout.tsx :这是我的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;

And lastly here is my _app.tsx :最后这里是我的_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;

Thanks for any help in advance.提前感谢您的任何帮助。

You need to return the provider in the context, and then reference the instance in _app.js.您需要上下文中返回提供者,然后在 _app.js 中引用该实例。

Here's my AuthContext (as an example).这是我的 AuthContext(作为示例)。 Don't worry about the specific code, but use my implementation as the foundation, and you'll be up and running in no time!不用担心具体的代码,但是以我的实现为基础,您很快就会启动并运行!

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>
  )

}

My _app.js file:我的 _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