【问题标题】:Unable to implement auth routes无法实现身份验证路由
【发布时间】:2019-04-27 04:04:52
【问题描述】:

我正在尝试学习反应,并正在我的应用程序中设置需要您登录的路由。我正在尝试调整给定的示例 here

我编写的代码应该重定向用户或显示受保护的路由。但是当我登录时,我仍然被重定向。

我相信问题出在我下面的 PrivateRoute 类中。我向它传递了一个在父类中设置的authenticated 属性,但它似乎没有更新。

在 app.js 中,我们声明了身份验证器,我们在其中与后端执行异步登录。

我将 checkLoggedIn 函数传递给登录组件,我们将父级的 authenticated 状态属性设置为 true。我console.log()ing 状态只是为了检查它正在发生,它就是这样。

当我点击Link/protected 路由时,我仍然被重定向。

app.js

// imports ... 

let authenticator = new Authenticator();

class ProtectedComponent extends Component {
    render() {
        return (
            <h1>Protected!</h1>
        );
    }
}

class App extends Component {
    constructor(props){
        super(props);
        this.state = {
            authenticator: authenticator,
            authenticated: authenticator.isLoggedIn(),
        }
    }

    checkLoggedIn() {
        this.setState({authenticated: true});
        console.log(this.state);
    }

    render() {
        let routes, links = null;
        links = <div className="links">
            <Link to="/login">Login</Link>
            <Link to="/protected">Protected</Link>
        </div>;

        routes = <div className="routes">
            <Route
                path="/login"
                render={() =>
                    <Login
                        authenticator={this.state.authenticator}
                        loginCallback={this.checkLoggedIn} />
                }
            />
            <PrivateRoute
                path="/protected"
                component={ProtectedComponent}
                authenticated={this.state.authenticated}
            />
        </div>;

        return (
            <Router className="App">
                {links}
                {routes}
            </Router>
        );
    }
}

export default App;

PrivateRoute.js

// imports .... 

const PrivateRoute = ({ component: Component, authenticated, ...rest }) => (
    <Route {...rest} render={props =>
            authenticated === true
                ? (<Component {...props} />)
                : (<Redirect to={{
                        pathname: "/login",
                        state: { from: props.location }
                    }} />
                )
    }/>
);

export default PrivateRoute;

登录.js

// imports ...

class Login extends Component {
    constructor(props) {
        super(props);
        this.authenticator = props.authenticator;
        this.loginCallback = props.loginCallback;
        this.state = {
            identifier: "",
            password: "",
        }
    }

    updateState = (e, keyName = null) => {
        this.setState({[keyName]: e.target.value})
    }

    attemptLogin = (e) => {
        this.authenticator.loginPromise(this.state.identifier, this.state.password)
            .then(resp => {
                if(resp.data.success === true) {
                    this.authenticator.setToken(resp.data.api_token);
                    this.loginCallback();
                } else {
                    this.authenticator.removeToken()
                }
            })
            .catch(err => {
                console.error(err);
            });
    }

    render(){
        <button onClick={this.attemptLogin}> Log In </button>
    }
}

export default Login;

我在回调方法中将身份验证状态设置为 true,但是当我转到受保护的路由(并运行它的渲染方法)时,它似乎评估为 false。

如果我对 react 道具系统有误解,请告诉我。如果您想查看更多代码,请告诉我,我会修改问题。

【问题讨论】:

  • 你可以像 this.props 这样在登录组件中直接使用 loginCallback()。 loginCallback 在你成功...

标签: javascript reactjs react-router


【解决方案1】:

你必须先创建一个 PrivateRoute HOC 组件:

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

export const PrivateRoute = ({ component: Component, ...rest }) => (
    <Route {...rest} render={props => (
        localStorage.getItem('bpm-user')
            ? <Component {...props} />
            : <Redirect to={{ pathname: '/login', state: { from: props.location } }} />
    )} />
)

并包装您最受保护的路线:

        <Switch>
            <Route path="/login" component={Login} />
            <PrivateRoute path="/new/index" component={NewIndex} />
            <PrivateRoute path="/jobs/index" component={JobsIndex} />
            <PrivateRoute path="/unions/index" component={UnionsIndex} />
            <PrivateRoute exact path="/" component={ListIndex} />
            <PrivateRoute exact path="/charges" component={MunicipalCharges} />
        </Switch>

并使用链接

<Link to="/jobs/index">Jobs</Link>

我的登录减速器

import axios from 'axios';
import * as actionTypes from './AuthActionTypes';

export const login = (user) => {
    return dispatch => {
        // for example => dispatch({type:actionTypes.REQUEST_LOGIN_USER});
        axios({
            method: 'post',
            url: '/api/auth/login',
            data: { 'username': user.username, 'password': user.password },
            headers: { 'Content-Type': 'application/json;charset=utf-8' }
        })
            .then(res => {
                localStorage.setItem('bpm-user', JSON.stringify(res.data));
                dispatch({
                    type: actionTypes.LOGIN_USER,
                    payload: res.data
                })
            })
            .catch(error => {
                 // TODO... for example => dispatch({type:actionTypes.FAILD_LOGIN_USER, payload:error});
            })
    }
}

export const logout = () => {
    localStorage.removeItem('bpm-user');
}

就像我从自己的项目中复制的示例代码

【讨论】:

  • 谢谢peyman,我决定遵循你的方法和布尔表达式而不是传递状态。
  • 欢迎您,我添加了我的登录减速器供您参考;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-21
  • 2011-07-12
  • 2012-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多