繁体   English   中英

如何在调用渲染方法之前从 API 获取数据? (反应,护照,快递)

[英]How do I fetch data from API before render method called? (react, passport, express)

我正在尝试验证用户是否已通过护照进行身份验证,然后才允许他们访问特定路线。 为此,我需要访问我的 API,它将返回我的用户的身份验证状态。 但是,我希望在路由渲染之前进行调用,以使路由保持受保护状态。 这是我目前的尝试:

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

class ProtectedRoute extends Component {
    constructor(){
        super()
        this.fetchAuthState().then(result => console.log('result',result))
        this.state = { 
            isAuth: false, 
            error: null
        }
    }
    async fetchAuthState() {
        try {
            const response = await fetch('http://localhost:3001/logincheck', {
              headers: {
                'content-type': 'application/json',
                accept: 'application/json',
              },
            });
            return await response.json();
          } catch (error) {
            console.error(error);
            this.setState({ error });
          }
      };

    render() {
      console.log('client check', this.state.isAuth)
      const { component: Component, ...props } = this.props
      return (
        <Route 
          {...props} 
          render={props => (
            this.state.isAuth ?
              <Component {...props} /> :
              <Redirect to='/login' />
          )} 
        />
      )
    }
  }

  export default ProtectedRoute; 

这是服务器端代码:

app.get('/logincheck', (req, res) =>{
  res.send(req.isAuthenticated())
})

我认为由于反应生命周期,应该在构造函数中调用 fetch,然后将其存储在 state 中。 但是,当我尝试直接或在临时变量中存储结果时,获取结果显示未定义。 我已经检查了护照文档中是否有任何客户端形式的 isAuthenticated(),但它似乎只适用于服务器端。 我正在考虑实施 jwt 令牌系统,以查看这是否是维护身份验证状态的更好方法,但认为使用 api 路由来检查会更容易。 我是 web 开发的新手,因此非常感谢任何建议/批评!

您可以添加一些加载屏幕,直到身份验证响应到达。

开始加载 state 并在组件安装时进行获取

class ProtectedRoute extends Component {
    constructor(){
        super()
        this.state = { 
            isAuth: false, 
            error: null,
            loading:true // default loading will be true
        }
    }
    componentDidMount(){
      this.fetchAuthState().then(result => this.setState({loading:false})) // after fetch end set loading false
    }
    ....
     render() {
      console.log('client check', this.state.isAuth)
      const { component: Component, ...props } = this.props
      return (
        {this.state.loading ? <LoadingComponent/> :<Route  
          {...props} 
          render={props => (
            this.state.isAuth ?
              <Component {...props} /> :
              <Redirect to='/login' />
          )} 
        />}
      )
    }
}

您可以通过添加一个额外的 state 变量(类似于loading )然后在 API 返回响应时切换它来完成此操作。 但我会稍微重构您的代码,使其看起来像这样:

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

class ProtectedRoute extends Component {
    constructor(){
        super()
        this.state = {
            loading: true,
            isAuth: false, 
            error: null
        }
    }
    componentDidMount(){
        fetch('http://localhost:3001/logincheck', {
              headers: {
                'content-type': 'application/json',
                accept: 'application/json',
              },
            })
            .then(res => res.json())
            .then(json => {
              this.setState({isAuth: json.isAuth, loading: false})
            })
            .catch(e => console.log(e))
      }

    render() {
      console.log('client check', this.state.isAuth)
      const { component: Component, ...props } = this.props;
      const {loading, isAuth} = this.state;
      return (
        <Route 
          {...props} 
          render={() => {
            return loading ?
                <div>Loading...</div>
                :
                isAuth ?
                   this.props.children
                :
                    <Redirect to='/login' />
        }} />
      )
    }
  }

  export default ProtectedRoute; 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM