【问题标题】:My react router dom Redirect path is not working . Its not popping any error but is not making my home page to private Route我的反应路由器 dom 重定向路径不起作用。它没有弹出任何错误,但没有将我的主页设为私有路由
【发布时间】:2020-06-12 10:22:23
【问题描述】:

我试图将我的主仪表板设为私有,即我的主页设为私有,我创建了一个名为私有路由的新组件,如果未通过身份验证但未重定向,则重定向到登录页面。 我想让它访问主页只有当用户可以登录并通过身份验证 这是我的私人路线

import React, {useContext} from 'react'
import {Route, Redirect} from 'react-router-dom';
import AuthContext from '../../context/auth/authContext';

const PrivateRoute = ({ component: Component, ...rest}) => {
    const authContext = useContext(AuthContext);
    const {isAuthenticated, loading} = authContext;
    return (
       <Route {...rest}
        render={props => 
        !isAuthenticated && !loading ? (
           <Redirect to='/login' />
       ) : (
           <Component {...props} />
       )} />
    );
};

export default PrivateRoute

authContext.js

import {createContext} from 'react';

const authContext = createContext();

export default authContext;

setAuthToken.js

import axios from 'axios';


const setAuthToken = token => {
  if(token){
      axios.defaults.headers.common['x-auth-token'] = token;
  }else{
      delete axios.defaults.headers.common['x-auth-token'];
  }
}

export default setAuthToken;

这是我的主要 app.js

import React, {Fragment} from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Navbar from './component/layout/Navbar';
import Alerts from './component/layout/Alerts';
import Home from './component/pages/Home';
import About from './component/pages/About';
import Register from './component/auth/Register';
import Login from './component/auth/Login';
import PrivateRoute from './component/routing/PrivateRoute';

import ContactState from './context/contact/ContactState'
import AuthState from './context/auth/AuthState'
import AlertState from './context/alert/AlertState'
import setAuthToken from './utils/setAuthToken'
import './App.css';

if(localStorage.token){
  setAuthToken(localStorage.token);
}

function App() {
  return (
    <AuthState>
    <ContactState>
    <AlertState>
    <Router>
      <Fragment>
      <Navbar />
      <div className="container">
      <Alerts />
       <Switch>
         <PrivateRoute exact path = '/' component={Home} />
         <Route exact path = '/about' component={About} />
         <Route exact path = '/register' component={Register} />
         <Route exact path = '/login' component={Login} />
       </Switch>
     </div>
      </Fragment>
    </Router>
    </AlertState>
    </ContactState>
    </AuthState>
  );
}

export default App;

login.js

import React, {useState, useEffect, useContext} from 'react'
import AlertContext from '../../context/alert/alertContext'
import AuthContext from '../../context/auth/authContext';

const Login = (props) => {
    const authContext = useContext(AuthContext);
    const alertContext = useContext(AlertContext);

    const {setAlert} = alertContext
    const {login, error, clearErrors, isAuthenticated} = authContext;

    useEffect(()=> {
        if(isAuthenticated){
            props.history.push('/');
        }
        if(error === 'Invalid Credentials'){
           setAlert(error, 'danger');
           clearErrors();
        }
        // eslint-disable-next-line
    }, [error, isAuthenticated, props.history]); 

    const[user, setUser] = useState({
        email: '',
        password: ''  
    });

    const {email, password} = user;


    const onChange = e => setUser({ ...user, [e.target.name]: e.target.value })

    const onSubmit = e => {
        e.preventDefault();
       if(email === '' || password=== ''){
           setAlert('Please fill in all fields', 'danger');
       }else{
           login({
               email,

           })
       }
    };


    return (
        <div className='form-container'>
        <h1>
            Account <span className="text-primary">Login</span>
        </h1>  
        <form onSubmit={onSubmit}>
            <div className="form-group">
                <label htmlFor="email">Email</label>
                <input type="email" name="email" value={email} onChange={onChange} />
            </div>
            <div className="form-group">
                <label htmlFor="password">Password</label>
                <input type="password" name="password" value={password} onChange={onChange} />
            </div>
            <input type="submit" value="Login" className="btn btn-primary btn-block"/>
        </form>          
        </div>
    )
}

export default Login;

注册.js

import React, {useState, useContext, useEffect} from 'react';
import AlertContext from '../../context/alert/alertContext'
import AuthContext from '../../context/auth/authContext';


const Register = (props) => {
    const authContext = useContext(AuthContext);
    const alertContext = useContext(AlertContext);

    const {setAlert} = alertContext
    const {register, error, clearErrors, isAuthenticated} = authContext;

    useEffect(()=> {
        if(isAuthenticated){
            props.history.push('/');
        }
        if(error === 'User already exists'){
           setAlert(error, 'danger');
           clearErrors();
        }
        // eslint-disable-next-line
    }, [error, isAuthenticated, props.history]); 
    const[user, setUser] = useState({ 
        name: '',
        email: '',
        password: '',
        password2: ''
    });

    const {name, email, password, password2} = user;


    const onChange = e => setUser({ ...user, [e.target.name]: e.target.value })

    const onSubmit = e => {
        e.preventDefault();
        if(name === '' || email === ''|| password === ''){
            setAlert('please enter all fields', 'danger')
        }else if (password !== password2){
            setAlert('password do not match', 'danger');
        }else{
            register({
                name,
                email,
                password
            });
         }
    };


    return (
        <div className='form-container'>
        <h1>
            Account <span className="text-primary">Register</span>
        </h1>  
        <form onSubmit={onSubmit}>
            <div className="form-group">
                <label htmlFor="name">Name</label>
                <input type="text" name="name" value={name} onChange={onChange} />
            </div>
            <div className="form-group">
                <label htmlFor="email">Email</label>
                <input type="email" name="email" value={email} onChange={onChange} />
            </div>
            <div className="form-group">
                <label htmlFor="password">Password</label>
                <input type="password" name="password" value={password} onChange={onChange} minLength="6" />
            </div>
            <div className="form-group">
                <label htmlFor="password2">Confirm Password</label>
                <input type="password" name="password2" value={password2} onChange={onChange} minLength="6" />
            </div>
            <input type="submit" value="Register" className="btn btn-primary btn-block"/>
        </form>          
        </div>
    )
}

export default Register

authState.js

import React, {useReducer} from 'react';
import AuthContext from './authContext' 
import axios from 'axios';
import authReducer from './authReducer'
import setAuthToken from '../../utils/setAuthToken'
import {
    REGISTER_SUCCESS,
    REGISTER_FAIL,
    USER_LOADED,
    AUTH_ERROR,
    LOGIN_SUCCESS,
    LOGIN_FAIL,
    LOGOUT,
    CLEAR_ERRORS
} from '../types'

const AuthState = props => {
    const initialstate = {
     token: localStorage.getItem('token'),
     isAuthenticated: null,
     loading: true,
     user: null,
     error: null
    };

    const  [state, dispatch] = useReducer(authReducer, initialstate);


    // Load user
    const loadUser = () => async () => {
       if(localStorage.token){
           setAuthToken(localStorage.token);
       }

        try {
            const res = await axios.get('/api/auth');
            dispatch({
                type: USER_LOADED,
                payload: res.data
            });
        } catch (error) {
            dispatch({ type: AUTH_ERROR })
        }
    };

    // Register user
    const register = async formData => {
        const config = {
            headers: {
                'Content-Type' : 'application/json'
            }
        }
        try {
            const res = await axios.post('/api/users', formData, config);

            dispatch({
                type: REGISTER_SUCCESS,
                payload: res.data
            });
            loadUser();
        } catch (error) {
            dispatch({ 
                type: REGISTER_FAIL,
                payload: error.response.data.msg
            })
        }
    }

    // Login user
    const login = async formData => {
        const config = {
            headers: {
                'Content-Type' : 'application/json'
            }
        }
        try {
            const res = await axios.post('/api/auth', formData, config);

            dispatch({
                type: LOGIN_SUCCESS,
                payload: res.data
            });
            loadUser();
        } catch (error) {
            dispatch({ 
                type: LOGIN_FAIL,
                payload: error.response.data.msg
            });
        }
    }

    // Logout
    const logout = () => dispatch({type: LOGOUT});

    // Clear errors
    const clearErrors = () => dispatch({type: CLEAR_ERRORS });




    return  (
        <AuthContext.Provider
        value={{
           token: state.token,
           isAuthenticated: state.isAuthenticated,
           loading: state.loading,
           user: state.user,
           error: state.error,
           register,
           loadUser,
           login,
           logout,
           clearErrors 
        }}
        >
            {props.children}
        </AuthContext.Provider>
    );
};

export default AuthState;

authreducer.js

import {
    REGISTER_SUCCESS,
    REGISTER_FAIL,
    USER_LOADED,
    AUTH_ERROR,
    LOGIN_SUCCESS,
    LOGIN_FAIL,
    LOGOUT,
    CLEAR_ERRORS,

} from '../types'

export default (state, action) => {
    switch(action.type) {
    case USER_LOADED:
        return {
            ...state,
            isAuthenticated: true,
            loading: false,
            user: action.payload
        }
     case REGISTER_SUCCESS:
     case LOGIN_SUCCESS:    
         localStorage.setItem('token', action.payload.token);
         return {
          ...state,
          ...action.payload,
          isAuthenticated: true,
          loading: false
         };
         case REGISTER_FAIL:
         case AUTH_ERROR:   
         case LOGIN_FAIL: 
         case LOGOUT:
             localStorage.removeItem('token');
             return {
                 ...state,
                 token: null,
                 isAuthenticated: false,
                 loading: false,
                 user: null,
                 error: action.payload
             };
             case CLEAR_ERRORS:
                 return {
                     ...state,
                     error: null
                 }
        default:
            return state;
    }
}

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    setAuthToken 是什么?你确认isAuthenticated已经是真的了吗

    也许你可以把你的完整代码放在codesandbox上,这样会更容易找到问题

    更新

    您应该在页面初始加载时从本地存储中读取令牌并更新 AuthContext 中的 isAuthenticated 布尔值。

    用户注销后,token必须清空,并将isAuthenticated设置为false

    import {createContext} from 'react';
    
    const token = localStorage.token;
    
    const authContext = createContext({
      isAuthenticated: token !== null && token !== 'undefined' && token !== '',
      loading: false,
    });
    
    export default authContext;
    

    【讨论】:

    • 我也添加了setauth令牌文件..我怎样才能直接输入完整的代码??
    • 你可以穿上codesandbox
    • 我看了你的代码,你的 authContext 没有实现,所以isAuthenticated 总是false 对吗?
    • 它仍然无法正常工作,我已经更新了我的 login.js 也帮助了我
    • 您的登录流程看起来不错。 USER_LOADEDLOGIN_SUCCESS 在做什么?请加authReducer
    【解决方案2】:

    AuthContext 中有什么内容?你对useContext 的使用对我来说很明显,但这取决于AuthContext 是什么,这就是控制你是否点击Redirect 的原因。

    【讨论】:

      猜你喜欢
      • 2017-09-17
      • 2020-10-22
      • 2020-02-05
      • 2019-06-02
      • 2019-10-03
      • 2023-04-07
      • 2020-11-12
      • 2017-09-03
      • 2022-10-12
      相关资源
      最近更新 更多