реакции-роутер-дом с реактивными перехватчиками не перенаправляет на правильный маршрут - PullRequest
0 голосов
/ 06 марта 2019

Я новичок, чтобы реагировать, и я уверен, что есть объяснение, которое я не понимаю, но я не могу найти ответ ...

Я хочу приложение, если пользователь вошел в систему, поэтому я следовал за некоторыминаправляю и создаю HOC (PrivateRoute), но по какой-то причине я продолжаю попадать на страницу входа в приложение,

Даже если localStorage содержит действительный JWT, и я спрашиваю конкретный путь (/ wallet / portfolio), он все еще перенаправляет меня на страницу входа, может кто-нибудь, пожалуйста, помогите мне понять проблему (я использую машинопись, но я уверен, что она не связана с проблемой)

Мой главный компонент (App.tsx)

//imports...

export const App = () => {
    const[jWTContext, setJWTContext] = useState(jWTContextInitialState);
    const[isLoggedIn, setIsLoggedIn] = useState(false);

    useEffect(() => {
        if (!isLoggedIn) {
            jWTContext.isValid().then(loggedIn => {
                    setIsLoggedIn(loggedIn);
                }
            ).catch(() => {setIsLoggedIn(false)});
        }
    });
    return (
        <JWTContext.Provider value={jWTContext}>
            <BrowserRouter>
                <Switch>
                    <PrivateRoute exact path="/wallet/portfolio"  component={AppPortfolio}  isSignedIn={isLoggedIn}/>
                    <Route exact path="/wallet/login" component={AppLogin} />
                    <Route exact path="/wallet/register" component={AppRegister} />
                    <Redirect to={isLoggedIn ? "/wallet/portfolio" : "/wallet/login"}/>
                </Switch>
            </BrowserRouter>
        </JWTContext.Provider>
    );
};

PrivateRoute.tsx (скопировано из руководства в Интернете ...)

import * as React from 'react';
import {Route, Redirect, RouteProps} from 'react-router-dom';

interface PrivateRouteProps extends RouteProps {
    component: any;
    isSignedIn: boolean;
}

const PrivateRoute = (props: PrivateRouteProps) => {
    const { component: Component, isSignedIn, ...rest } = props;

    return (
        <Route
            {...rest}
            render={(routeProps) =>
                isSignedIn ? (
                    <Component {...routeProps} />
                ) : (
                    <Redirect
                        to={{
                            pathname: '/wallet/login',
                            state: { from: routeProps.location }
                        }}
                    />
                )
            }
        />
    );
};

export default PrivateRoute;

JWTContext.tsx (поставщик My Context):

import React from 'react';
import {JWTBody, JWTHeader, JWTToken} from "../interfaces/JWTToken"

export interface JWTContext {
    jWTToken: JWTToken | null;
    setJWTToken(jWTToken: JWTToken | null): void;
    isValid(): Promise<boolean>;
    updateFromLocalStorage(): (JWTToken | null);
}

export const jWTContextInitialState : JWTContext = {
    jWTToken: initFromLocalStorage(),

    setJWTToken: (jWTToken) => {
        jWTContextInitialState.jWTToken = jWTToken;
    },

    isValid: async() => {
        if (jWTContextInitialState.jWTToken) {
            let response = await fetch("/auth/tokenvalid",{
                method: "GET",
                headers: {
                    "Content-Type": "application/json",
                    "Authorization": JSON.stringify(jWTContextInitialState.jWTToken)}});
            let res = await response.json();
            if (res.code === 200)
                return true;
        }
        return false;
    },

    updateFromLocalStorage: () => {
        return initFromLocalStorage()
    }
};

function initFromLocalStorage() {
    let localStorageToken = localStorage.getItem("velonaJWT");
    if (localStorageToken) {
        return parseJwt(localStorageToken);
    }
    return null;
}


function parseJwt (token: string): JWTToken {
    token = token.replace("Bearer ", "");
    let tokenArray = token.split('.');

    let header = tokenArray[0];
    header = header.replace('-', '+').replace('_', '/');
    let bufferHeader = Buffer.from(header, "base64");
    let dataHeader: JWTHeader =  JSON.parse(bufferHeader.toString());

    let body = tokenArray[1];
    body = body.replace('-', '+').replace('_', '/');
    let bufferBody = Buffer.from(body, "base64");
    let dataBody: JWTBody =  JSON.parse(bufferBody.toString());

    return ({
        header: dataHeader,
        body: dataBody,
        sig: tokenArray[2]
    });
    //return  JWTToken(JSON.parse(bufferHeader.toString()), JSON.parse(bufferBody.toString()), tokenArray[2])
}


export const JWTContext = React.createContext(jWTContextInitialState);

инаконец (JWTToken.tsx -> только для интерфейсов)


// represent velona WJT token
export interface JWTToken {
    header: JWTHeader,
    body: JWTBody,
    sig: string,
}

export interface JWTHeader {
    typ: string,
    alg: string
}

export interface JWTBody {
    sub: number,
    jti: string,
    authorities: Authorities[],
    iat: number,
    nbf: number,
    exp: number,
    environment: string
}

export enum Authorities {
    ROLE_USER,
    ROLE_TRUSTEE,
    ROLE_EMPLOYEE,
    ROLE_ADMIN
}

1 Ответ

0 голосов
/ 06 марта 2019

@ Tholle помог мне понять проблему, потому что сначала пользователь не проходит аутентификацию (до тех пор, пока JWT не аутентифицируется сервером -> async), нам нужно добавить следующее в реагирующий коммутатор:

<BrowserRouter>
    <Switch>
        <PrivateRoute exact path="/wallet/portfolio"  component={AppPortfolio}  isSignedIn={isLoggedIn}/>
                    /*all other private routes here*/
        { isLoggedIn ? <Redirect to="/wallet/portfolio"/> : "" }
        <Route exact path="/wallet/login" component={AppLogin} />
        <Route exact path="/wallet/register" component={AppRegister} />
        <Redirect to={isLoggedIn ? "/wallet/portfolio" : "/wallet/login"}/>
    </Switch>
</BrowserRouter>

Конечно, недостатком является то, что если пользователь вошел в систему, он не сможет перейти ни на одну общедоступную страницу (например, при регистрации), но я могу с этим смириться ...

спасибо @ Tholle

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...