如何等待异步响应

如何等待异步响应

本文介绍了PrivateRoute - 如何等待异步响应?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 PrivateRoute 来验证令牌是否有效并且它是一个异步函数.问题是:我对渲染视图的验证不起作用,它总是在渲染:

I have a PrivateRoute that verify if a token is valid and it's an async function. The problem is: my validation to render a view is not working, it's always rendering:

App.js

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

const Routes = () => (
  <BrowserRouter>
    <Fragment>
      <Switch>
        <Route exact path="/" component={SignIn} />
        <PrivateRoute path="/app" component={App} />
      </Switch>
      <ModalContainer />
    </Fragment>
  </BrowserRouter>
);

export default Routes;

auth.js

import axios from 'axios'

export const isAuthenticated = async () => {
  const isValidRequest = false;

  const resp = await axios.get('http://127.0.0.1:8080...')
  data = resp.data;
  console.log(data);

  ....// more code

  return isValidRequest;
}

如何确保 PrivateRoute 将等待函数 isAuthenticated()?

How can I ensure that PrivateRoute will wait for function isAuthenticated()?

更新 1:

const Routes = () => {
  const [state, setState] = useState({isLoading: true, authenticated: false});
  useEffect(() => {
    async function checkAuth() {
        const isAuth = await isAuthenticated();
        setState({isLoading: false, authenticated: isAuth});
    }
  }, []);

  if(state.isLoading) {
     return <div>Loading....</div>
  }
  return (
    <BrowserRouter>
      <Fragment>
        <Switch>
          <Route exact path="/" component={SignIn} />
          <PrivateRoute path="/app" isAuthenticated={state.authenticated} component={App} />
        </Switch>
        <ModalContainer />
      </Fragment>
    </BrowserRouter>
  );

}

推荐答案

不是在所有 PrivateRoutes 中调用 isAuthenticated,而是在 Routes 组件中调用一次 这样检查只执行一次,然后将值作为 prop 传递.另请注意,在获取数据时保持加载状态

Instead of calling isAuthenticated in all PrivateRoutes, you call it once in your Routes component so that the check is only performed once and then pass on the value as prop. Also note that while the data is being fetched maintain a loading state

请注意,您的 isAuthenticated 函数是一个异步函数,因此您必须等到承诺得到解决.您可以使用 async-await 或使用传统的 promise 方法

Note, that your isAuthenticated function is an async function so you have to wait till the promise is resolved. You can use async-await or go by the traditional promise approach

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

const Routes = () => {
    const [state, setState] = useState({isLoading: true, authenticated: false});
    useEffect(() => {
      async function checkAuth() {
         const isAuth = await isAuthenticated();
         setState({isLoading: false, authenticated: isAuth});
     }
      checkAuth();
   }, []);
    if(state.isLoading) {
       return <Loader/>
    }
    return (
      <BrowserRouter>
        <Fragment>
          <Switch>
            <Route exact path="/" component={SignIn} />
            <PrivateRoute path="/app" isAuthenticated={state.authenticated} component={App} />
          </Switch>
          <ModalContainer />
        </Fragment>
      </BrowserRouter>
    );

}

export default Routes;

更新:由于您没有使用react v16.8.0及以上版本,可以使用类组件来实现上述逻辑


Update: Since you do not use v16.8.0 or above of react, you can implement the above logic by using a class componnet

class Routes extends React.Component {
    state = {isLoading: true, authenticated: false};

    async componentDidMount() {
         const isAuth = await isAuthenticated();
         this.setState({isLoading: false, authenticated: isAuth});
    }

    render() {
        if(state.isLoading) {
           return <Loader/>
        }
        return (
          <BrowserRouter>
            <Fragment>
              <Switch>
                <Route exact path="/" component={SignIn} />
                <PrivateRoute path="/app" isAuthenticated={state.authenticated} component={App} />
              </Switch>
              <ModalContainer />
            </Fragment>
          </BrowserRouter>
        );
      }

}

export default Routes;

这篇关于PrivateRoute - 如何等待异步响应?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-16 06:50