ReactJS + NodeJS:如果未登录,如何正确重定向用户?

时间:2018-08-26 17:58:13

标签: node.js reactjs passport.js

我有一个受保护的URL-如果用户试图呈现不允许访问的页面(这是在ReactJS组件中),这是我如何重定向用户的方法:

render() {
  if(!this.props.auth.isAuthenticated) {
    this.props.history.push('/');
  }
  ...

他未登录时,已在主页上重定向。但是在控制台中,我遇到了这两个错误:

index.js:2178 Warning: Cannot update during an existing state transition (such as within `render` or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to `componentWillMount`.

该消息表明我可以将if块移动到componentWillMount吗?但是,componentWillMount是否不被淘汰?

和第二条错误消息:

xhr.js:178 GET http://localhost:3000/api/cars 401 (Unauthorized)

此消息是由NodeJS路由中的以下代码块引起的:

router.get('/cars', passport.authenticate('jwt'), function(req, res, next) {
    if (req.isAuthenticated()) {
        console.log('logged in');

        Car.find({}).sort('name').exec(function(err, cars) {
            if(err) throw err;
            res.send(JSON.stringify(cars));
        });
    } else {
        // not logged in
        console.log('not logged in');
        //res.send(401);
    }
});

如果用户未通过身份验证,则控制台中会引发401错误,并且不会执行此路由内的代码。这是正确的行为吗?为什么控制台中仍然存在错误?

编辑: ReactJS组件:

class Car extends Component {
    constructor() {
        super();
        this.state = {
            name: '',
            errors: {},
            cars: []
        }
        this.handleInputChange = this.handleInputChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    UNSAFE_componentWillMount() {
        if(!this.props.auth.isAuthenticated) {
            this.props.history.push('/');
        }
    }

    componentDidMount() {
        //console.log('x');
        //console.log(this.props.auth);
        //let self = this;
        axios.get('/api/cars')
            .then((response) => {
                this.setState({cars: response.data});
            }).catch(err => {
                console.log('CAUGHT IT! -> ', err);
                if (err.response.status === 401) {
                    //this.props.history.push('/');
                }
                return err;
            })
    }

    componentWillReceiveProps(nextProps) {
        if(nextProps.auth.isAuthenticated) {
            this.props.history.push('/')
        }
        if(nextProps.errors) {
            this.setState({
                errors: nextProps.errors
            });
        }
    }

    handleInputChange(e) {
        this.setState({
            [e.target.name]: e.target.value
        })
    }

    handleSubmit(e) {
        e.preventDefault();
        const car = {
            name: this.state.name
        }
        console.log(car);
        axios.post('/api/cars/create', car)
            .then(function(response) {
                console.log('response.data: ', response.data);
                if(response.data == "success"){
                    console.log('successssss');
                }
            }).catch(function(err) {
                console.log(err)
            });
    }


    render() { ...

3 个答案:

答案 0 :(得分:0)

请避免在一个堆栈溢出问题中提出多个问题


错误1:

该错误消息明确指出,您不应导航到render方法中的另一个页面。但是,您正在这样做。消息提示您可以在componentWillMount livecycle方法中移动代码,但请注意,此检查将不会在每次重新渲染时运行。

错误2:

您似乎正在呼叫此路由,该路由未经身份验证而受到身份验证的保护。没有看到您的客户端代码,我无法进一步评论。

答案 1 :(得分:0)

Patrick解释了上述错误。 componentWillMount生命周期方法。据我所知,不被弃用。

我猜您正在使用React Router满足您的路由需求。 react router private route example是如何正确执行此操作的一个很好的示例 它使用来自react-router-dom的Route和Redirect并创建一个特殊的PrivateRoute组件。对于需要身份验证并重定向未经授权的用户的每条路由,您将使用此PrivateRoute组件,而不仅仅是Route组件。

您可以检查身份验证,并在需要时在render Lifecycle方法内渲染其他内容。但是您不应该从render方法内部重定向。

答案 2 :(得分:0)

您可以这样重定向用户:

import {Redirect} from 'react-router-dom';

...//inside constructor
this.state={
        redirect_path:''//redirect_path is the path you want to redirect the user to
}

在componentDidMount中,检查用户是否已获得授权,

如果不是:

this.setState({
           redirect_path:'path_to_redirect_to'   
})

在渲染方法中:

render()
{ //push will add it to the browser history
    if(this.state.redir)
    {
       return(
            <Redirect push to={this.state.redirect_path} />
    }
    else
    {
       //return the page 
    }

 }