在通过Google OAuth登录后,用户被重定向到主页,他们的用户数据存储在本地存储中.这样做的目的是在导航栏上立即显示用户的姓名和个人资料,而无需刷新页面.目前,此信息仅在页面刷新后才可见.所需的功能是在登录时将用户重定向到主页,并在导航栏上立即显示登录详细信息.

Auth.js

import React, { useState } from 'react'
import { Avatar, Button, Paper, Grid, Typography, Container, TextField } from '@mui/material'
import LockClockOutlinedIcon from '@mui/icons-material/LockClockOutlined';
import { GoogleLogin } from '@react-oauth/google';
import { useDispatch } from 'react-redux';
import { jwtDecode } from "jwt-decode";
import { AUTH } from '../constants/actionTypes';
import { setAuthData } from '../../reducers/auth';
import useStyles from './styles'
import Input from './Input';
import Icon from './icon'
import { useNavigate } from 'react-router-dom';

export default function Auth() {
  const [isSignup,setIsSignUp] = useState(false)
  const classes = useStyles()
  const [showPassword, setShowPassword] = useState(false)
  const dispatch = useDispatch()
  const navigate = useNavigate()

  const handleSubmit = () => {

  }
  const handleChange = () => {

  }

  const handleShowPassword = () => {
    setShowPassword((prevpassowrd) => !prevpassowrd)
  }

  const switchMode = () => {
    setIsSignUp((prevflag) => !prevflag)

  }
  const googleSucess = async (res) => {
    
    
      // if profile obj exists it returns or else it throws an error
    // const token = jwtDecode(res.credential).jti
    // console.log("this is token", token)
  

    try {
          const cred = res.credential
          dispatch(setAuthData(cred))
          navigate('/')
    }catch (error){
      console.log("error dispatching", error)

    }
   

  }
  const googleFailure = (error) => {
    console.error('Sign-in failed:', error);
      
      
  }


  return (
    <Container component='main' maxWidth="xs">
      <Paper className={classes.paper} elevation={3}>
        <Avatar className={classes.avatar}>
          <LockClockOutlinedIcon />
        </Avatar>
        <Typography variant='h5'>{isSignup ? 'Sign Up' : 'Sign In'}</Typography>
        <form className={classes.form} onSubmit={handleSubmit}>
          <Grid container spacing={2}>
            {
              isSignup && (
                <>
                
                  <Input name='firstName' label='First Name' handleChange={handleChange} autoFocus half />
                  <Input name='lastName' label='Last Name' handleChange={handleChange} half />

                </>
              )
            }
            <Input name='email' label='Email Address' handleChange={handleChange} type='email' />
            <Input name='password' label='Password' handleChange={handleChange} type={showPassword ? 'text' : 'password'}
              handleShowPassword={handleShowPassword} />
            {isSignup &&
              <Input name='confirmpassword' label='Confirm Password' handleChange={handleChange} type='password' />}

          </Grid>
          
          <Button type='submit' fullWidth variant='contained' color='primary' style={{ marginTop: '15px', marginBottom : '15px' }}>
            {isSignup ? 'Sign Up' : 'Sign In'}
          </Button>
          <GoogleLogin 
          
            clientId='client id goes here'
            render={(renderProps) => (
              <Button 
              style={{ marginTop: '15px' }}
              className={classes.googleButton} 
              color='primary' 
              fullWidth 
              onClick={renderProps.onClick} 
              disabled = {renderProps.disabled}
              startIcon={<Icon />} 
              variant='contained'

              >Google {isSignup ? 'Sign Up' : 'Sign In'}</Button>
            ) }
            onSuccess={googleSucess}
            onFailure={googleFailure}
            cookiePolicy='single_host_origin'
            plugin_name = 'dont work'
            />
      
          <Grid container justify = 'center'>
            <Grid item style={{ marginTop: '15px', textAlign: 'center' }}>
                  <Button onClick={switchMode} style={{ marginTop: '15px', textAlign: 'center' }}>
                    {isSignup ? 'Already Have an account? Sign In' : 'Don\'t have account? Sign Up'}
                  </Button>
            </Grid>
          </Grid>
        </form>
      </Paper>
    </Container>
  )
}

reducers_Auth.js

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { jwtDecode } from "jwt-decode";

const initialState = {
  authData: null,
};

const authSlice = createSlice({
    name: 'auth',
    initialState,
    reducers: {
        setAuthData(state, action) {
            const user_data = jwtDecode(action.payload);

            // Modify the draft state using Immer
            state.authData = user_data;
      
            // Update localStorage outside of Immer
            localStorage.setItem('profile', JSON.stringify(user_data));
        },
        logoutAuth(state, action) {
            localStorage.removeItem('profile')
        }
    }
})

export const { setAuthData, logoutAuth } = authSlice.actions;
export default authSlice.reducer;

没有bar.js

import { AppBar, Typography, Toolbar, Avatar, Button, Box,Grid,Container } from "@mui/material";
import React, { useEffect, useState } from "react";
import { Link } from 'react-router-dom'
import useStyles from './styles'
import memories from '../../images/memories.png'
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
import { logoutAuth } from "../../reducers/auth";

const Navbar = () => {
    const classes = useStyles()
    const dispatch = useDispatch()
    const navigate = useNavigate()

    const [user,setUser] = useState(JSON.parse(localStorage.getItem('profile')))
    useEffect(() => {
        if (user) {
            setUser(JSON.parse(localStorage.getItem('profile')))
        }
        
    }, [])

    const logout = () => {
        dispatch(logoutAuth())
        navigate('/auth')
        setUser(null)
    }
  
    return (
        // <Box sx={{ flexGrow: 1 }}>
        <>
            <AppBar className={classes.appBar} position='static' color='inherit'>
                <Container maxWidth="xl" style={{ display: 'flex', flexDirection: 'row' }}>
                    <div className={classes.brandContainer}>
                        <img className={classes.image} src={memories} alt="memories" height="50" />
                        <Typography variant='h4' nowrap className={classes.heading} >Travel Blog</Typography>
                    </div>
                    <Toolbar className={classes.toolbar} style={{ marginLeft: 'auto' }}>
                        {user ? (
                            <div className={classes.profile}>
                                <Avatar className={classes.purple} alt={user.name} src={user.picture}>{user.name.charAt(0)}</Avatar>
                                <Typography className={classes.userName} variant='h6'>{user.name}</Typography>
                                <Button variant="contained" className={classes.logout} color="secondary" onClick={logout} >Logout</Button>
                            </div>
                        ) : (
                                <Button component={Link} to="/auth" variant="contained" color="primary" style={{ marginLeft: 'auto' }}>
                                    Sign In
                                </Button>
                           
                        )}
                    </Toolbar>
                </Container>
            </AppBar>
        </>
    )
}

export default Navbar

推荐答案

Navbar组件应该读取存储在Redux状态中的用户数据,而不是存储在LocalStorage中的数据.对本地存储的更新不会触发对重新呈现的react .

示例:

...
import { useDispatch, useSelector } from "react-redux";
...

const Navbar = () => {
  const classes = useStyles();
  const dispatch = useDispatch();
  const navigate = useNavigate();

  const user = useSelector(state => state.auth.authData);

  const logout = () => {
    dispatch(logoutAuth());
    navigate('/auth');
  };
  
  return (
    ...rendered UI with user data...
  );
};

export default Navbar;

logoutAuth操作应重置身份验证状态.从本地存储中查询初始身份验证状态.

const initialState = {
  authData: JSON.parse(localStorage.getItem("profile")),
};

const authSlice = createSlice({
  name: 'auth',
  initialState,
  reducers: {
    setAuthData(state, action) {
      const user_data = jwtDecode(action.payload);

      state.authData = user_data;
      
      localStorage.setItem('profile', JSON.stringify(user_data));
    },
    logoutAuth(state, action) {
      localStorage.removeItem('profile');
      state.authData = null; // <-- reset to initial
    },
  },
});

Javascript相关问答推荐

具有相同参数的JS类

使用下表中所示的值初始化一个二维数组

我可以从React中的出口从主布局调用一个处理程序函数吗?

D3 Scale在v6中工作,但在v7中不工作

cypress中e2e测试上的Click()事件在Switch Element Plus组件上使用时不起作用

获取Uint8ClampedArray中像素数组的宽度/高度

如何在ASP.NET中使用Google Charts API JavaScript将条形图标签显示为绝对值而不是负值

这个值总是返回未定义的-Reaction

检索相加到点的子项

Puppeteer上每页的useProxy返回的不是函数/构造函数

try 使用PM2在AWS ubuntu服务器上运行 node 进程时出错

如果一个字符串前面有点、空格或无字符串,后面有空格、连字符或无字符串,则匹配正则表达式

使用Document.Evaluate() Select 一个包含撇号的HTML元素

我怎样才能得到一个数组的名字在另一个数组?

Django模板中未加载JavaScript函数

如何在Firebase中读取对象的特定字段?

Played link-Initialize.js永远显示加载符号

使用Java脚本替换字符串中的小文本格式hashtag

通过ng-绑定-html使用插入的HTML中的函数

浮动标签效果移除时,所需的也被移除