React - Firebase 身份验证和 useContext
React - Firebase authentication and useContext
我正在尝试找出创建全局状态变量的最佳方法,该变量将保存 firebase 身份验证用户 ID。
例如,下面的代码将检查用户是否已登录,如果成功则将他们发送到欢迎页面。
但我还需要在不同的文件上设置私有路由,我希望能够共享 getId 状态。我读到 useContext 可以做到这一点,但不确定如何实现它。请指教,谢谢
const [getId, setId] = useState("");
const login = async ( id ) => {
return setId(id);
};
firebase.auth().onAuthStateChanged((user) => {
if (user) {
login(user.uid).then(() => {
history.push("/welcome");
});
} else {
history.push("/");
}
});
const PrivateRoute = ({ getId, component: Component, ...rest }) => (
<Route
{...rest}
component={(props) =>
getId ? (
<div>
<Component {...props} />
</div>
) : (
<Redirect to="/" />
)
}
/>
);
我会给你 我的 示例来获得 Auth 上下文。以下是部分:
_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>
)
}
重要的项目是 <AuthProvider>
组件。这就是包装上下文的地方。
AuthContent.js 文件:
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>
)
}
这是存储和访问状态的地方,包括所有助手(注册、注销、登录等)。
使用方法:
import { Button, Card, CardHeader, CardContent, Link, TextField, Typography } from '@material-ui/core'
import { motion } from 'framer-motion'
import { useRef, useState } from 'react'
import { useAuth } from '../contexts/AuthContext'
import { useRouter } from 'next/router'
export default function SignupForm() {
const router = useRouter()
const { signUp } = useAuth()
const [state, setState] = useState({
email: "",
password: "",
passwordConfirm: ""
})
const [error, setError] = useState("")
function handleForm(e) {
setState({
...state,
[e.target.name]: e.target.value
})
}
async function handleSubmit(e) {
if (state.password !== state.passwordConfim) {
setError("Passwords do not match")
}
await signUp(state.email, state.password)
.catch(err => console.log(JSON.stringify(err)) )
router.push("/account")
}
return(
<motion.div>
<Card >
<CardHeader title="Header" />
<CardContent>
<TextField label="email" name="email" variant="outlined" onChange={ handleForm } />
<TextField label="password" name="password" type="password" variant="outlined" onChange={ handleForm } />
<TextField label="Password Confirmation" name="passwordConfirm" type="password" variant="outlined" onChange={ handleForm } />
{error && <Alert severity="error" variant="filled" >{error}</Alert>}
<Button onClick={ handleSubmit }>
<Typography variant="button">Sign Up</Typography>
</Button>
</CardContent>
</Card>
</motion.div>
)
}
您从您的上下文中导入 { useAuth }
(我通常将我的放在上下文文件夹中)然后您可以通过解构调用组件内部变量的实例(例如 const { currentUser, login } = useAuth()
)
我正在尝试找出创建全局状态变量的最佳方法,该变量将保存 firebase 身份验证用户 ID。 例如,下面的代码将检查用户是否已登录,如果成功则将他们发送到欢迎页面。
但我还需要在不同的文件上设置私有路由,我希望能够共享 getId 状态。我读到 useContext 可以做到这一点,但不确定如何实现它。请指教,谢谢
const [getId, setId] = useState("");
const login = async ( id ) => {
return setId(id);
};
firebase.auth().onAuthStateChanged((user) => {
if (user) {
login(user.uid).then(() => {
history.push("/welcome");
});
} else {
history.push("/");
}
});
const PrivateRoute = ({ getId, component: Component, ...rest }) => (
<Route
{...rest}
component={(props) =>
getId ? (
<div>
<Component {...props} />
</div>
) : (
<Redirect to="/" />
)
}
/>
);
我会给你 我的 示例来获得 Auth 上下文。以下是部分:
_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>
)
}
重要的项目是 <AuthProvider>
组件。这就是包装上下文的地方。
AuthContent.js 文件:
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>
)
}
这是存储和访问状态的地方,包括所有助手(注册、注销、登录等)。
使用方法:
import { Button, Card, CardHeader, CardContent, Link, TextField, Typography } from '@material-ui/core'
import { motion } from 'framer-motion'
import { useRef, useState } from 'react'
import { useAuth } from '../contexts/AuthContext'
import { useRouter } from 'next/router'
export default function SignupForm() {
const router = useRouter()
const { signUp } = useAuth()
const [state, setState] = useState({
email: "",
password: "",
passwordConfirm: ""
})
const [error, setError] = useState("")
function handleForm(e) {
setState({
...state,
[e.target.name]: e.target.value
})
}
async function handleSubmit(e) {
if (state.password !== state.passwordConfim) {
setError("Passwords do not match")
}
await signUp(state.email, state.password)
.catch(err => console.log(JSON.stringify(err)) )
router.push("/account")
}
return(
<motion.div>
<Card >
<CardHeader title="Header" />
<CardContent>
<TextField label="email" name="email" variant="outlined" onChange={ handleForm } />
<TextField label="password" name="password" type="password" variant="outlined" onChange={ handleForm } />
<TextField label="Password Confirmation" name="passwordConfirm" type="password" variant="outlined" onChange={ handleForm } />
{error && <Alert severity="error" variant="filled" >{error}</Alert>}
<Button onClick={ handleSubmit }>
<Typography variant="button">Sign Up</Typography>
</Button>
</CardContent>
</Card>
</motion.div>
)
}
您从您的上下文中导入 { useAuth }
(我通常将我的放在上下文文件夹中)然后您可以通过解构调用组件内部变量的实例(例如 const { currentUser, login } = useAuth()
)