【问题标题】:Consume React.createContext() implemented in _app.js使用 _app.js 中实现的 React.createContext()
【发布时间】:2020-11-05 22:42:50
【问题描述】:

我想从另一个组件的上下文中访问emailLogin

userContext.js

import React, { useEffect, useState } from 'react';
import cookie from 'js-cookie';
import {firebase} from './firebase-client';

export const UserContext = React.createContext();
const tokenName = 'firebaseToken';

const UserProvider = ({ children }) => {
  const emailLogin = async (email, password, redirectPath) => {
    await firebase
      .auth()
      .signInWithEmailAndPassword(email, password)
      .then(() => {
        console.log('User logged in.');
      })
      .catch((err) => {
        console.log(err);
      });
  };

  const onAuthStateChange = () => {
    return firebase.auth().onAuthStateChanged(async (user) => {
      if (user) {
        const token = await user.getIdToken();
        cookie.set(tokenName, token, { expires: 14 });
      } else {
        cookie.remove(tokenName);
      }
    });
  };

  useEffect(() => {
    const unsubscribe = onAuthStateChange();
    return () => {
      unsubscribe();
    };
  }, []);
    
      return <UserContext.Provider value={{ emailLogin }}>{children}</UserContext.Provider>;
    };
    
    export default UserProvider;

_app.js

import React from 'react';
import Head from 'next/head';
import App from 'next/app'
import cookies from 'next-cookies'
import UserProvider from '../lib/userContext'
import { ThemeProvider } from '@material-ui/core/styles';
import CssBaseline from '@material-ui/core/CssBaseline';
import theme from '../theme';

export default function MyApp(props) {
  const { Component, pageProps, user } = props;

  React.useEffect(() => {
    const jssStyles = document.querySelector('#jss-server-side');
    if (jssStyles) {
      jssStyles.parentElement.removeChild(jssStyles);
    }
  }, []);

  return (
    <React.Fragment>
      <Head>
        <title>My app</title>
        <meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
      </Head>
      <ThemeProvider theme={theme}>
        <CssBaseline />
        <UserProvider>
          <Component {...{...pageProps, ...user}} />
        </UserProvider>
      </ThemeProvider>
    </React.Fragment>
  );
}
MyApp.getInitialProps = async (userContext) => {
  const { ctx } = userContext;
  let error;
  const appProps = await App.getInitialProps(userContext);
  const { firebaseToken } = cookies(ctx);
  if (firebaseToken) {
    try {
      const headers = {
        'Context-Type': 'application/json',
        Authorization: JSON.stringify({ token: firebaseToken }),
      };
      const dev = process.env.NODE_ENV === 'development';
      const server = dev ? 'http://localhost:3000' : 'https://firebase-app-taupe.vercel.app/';
      const result = await fetch(`${server}/api/validate`, { headers }).then((res) => res.json());
      return { ...result, ...appProps };
    } catch (e) {
      console.log(e);
    }
  }
  return { ...appProps };
};

auth.js

import { useContext } from 'react'
import Button from '@material-ui/core/Button'
import {Grid, TextField} from '@material-ui/core'
import UserContext from '../lib/userContext'


const auth = () => {
    const { emailLogin } = useContext(UserContext);
  return (
    <Grid container spacing={0} direction="column" alignItems="center" justify="center" style={{ minHeight: '100vh' }}>
      <Grid item>
        <div>
          <TextField value="diegopitt@gmail.com" label="email" /><br /><br />
          <TextField value="12345678" label="password" type="password" /><br /><br />
          <Button variant="contained" color="primary"  onClick={() => login('diegopitt@gmail.com', '12345678')}>Sign In</Button>
        </div>
      </Grid>   
    </Grid> 
  )
}

export default auth

如何从 auth 组件访问函数 emailLogin?

【问题讨论】:

  • 您是否尝试过从您获得的上下文中调用该方法?喜欢let ctx = useContext(UserContext); ctx.emailLogin(...)
  • 不知道该怎么做。你能发布解决方案吗?
  • 在我的身份验证组件中,我有一个登录表单,我想访问“emailLogin”进行验证
  • 好的,那我发个答案试试

标签: reactjs next.js


【解决方案1】:

当您将对象作为上下文值传递时,每当您想使用 rmail 字段时,您都可以执行以下操作:

const ctx = useContext(UserContext);
ctx.emailLogin(...)

以便访问emailLogin 字段。或者更简单:const { emailLogin } = useContext(UserContext);

别忘了先导入UserContext

【讨论】:

  • 我收到 TypeError: Cannot destructure property 'emailLogin' of 'Object(...)(...)' as it is undefined. 我更新了问题以显示 auth.js 我尝试访问的位置 emailLogin
  • 我可以看到console.log 或上下文对象的结果吗??
  • 500(内部服务器错误)
  • 这意味着在运行过程中的某个时刻服务器出现错误。为了查看在哪里,我建议在您捕获并记录错误的每一点,添加一个错误前缀。它将帮助我们了解它是来自您的服务器还是来自 firebase 的服务器。在userContext.js 中可能是console.log('Login error', err);_app.jsconsole.log('Request error', err);
  • auth 组件中,您使用UserProvider 而不是UserContext 作为useContext arg
猜你喜欢
  • 2018-12-05
  • 2020-02-18
  • 1970-01-01
  • 2020-05-16
  • 2019-07-21
  • 2019-06-15
  • 1970-01-01
  • 2021-09-13
  • 2021-11-03
相关资源
最近更新 更多