React 上的 Async / Await 不起作用。什么都不起作用
2020-04-14
1483
好吧,说其他一切都经过测试并且运行良好,我创建了这个
PublicRoute
,它向
NodeJS
发送请求,但函数
isAuthenticated
从不等待来自后端的响应,并且始终返回
promise
而不是
true
或
false
。我在互联网上到处搜索,但没有找到解决方案。我不知道如何让它等待。
PublicRoute 文件:
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import { useAuth } from '../context/auth';
import api from '../services/api'; // Axios.
function PublicRoute( { component: Component, ...rest } ) {
const { authTokens } = useAuth();
async function isAuthenticated ( token ) {
if ( token === undefined ) return false;
const data = {
token
};
try {
const response = await api.post( '/cT', data );
if ( response.status === 200 ) {
console.log( 'Retorned true.' );
return true;
} else {
console.log( 'Retorned false.' );
return false;
}
} catch ( error ) {
console.log( 'Retorned false with error.' );
console.log( error );
return false;
};
}
const estaAutenticado = isAuthenticated( authTokens );
console.log( 'Is authenticated?' );
console.log( estaAutenticado ); // It was supposed to return true or false, but always returns a promise.
return (
<Route { ...rest }
render={
( props ) => ( estaAutenticado === true ) ?
( <Redirect to='/profile' /> ) :
( <Component { ...props } /> )
}
/>
);
}
export default PublicRoute;
这是我的 Routes 文件:
import React, { useState } from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import { AuthContext } from './context/auth';
// Pages:
import PublicRoute from './pages/PublicRoute';
import PrivateRoute from './pages/PrivateRoute';
import Admin from './pages/Admin';
import Logon from './pages/Logon';
import Register from './pages/Register';
import User from './pages/Register/User';
import Ong from './pages/Register/Ong';
import Profile from './pages/Profile';
import NewIncident from './pages/NewIncident';
export default function Routes( props ) {
const localStorageToken = localStorage.getItem( 'token' );
let existingTokens = undefined;
if ( localStorageToken !== 'undefined' ) {
existingTokens = JSON.parse( localStorage.getItem( 'token' ) );
}
const [ authTokens, setAuthTokens ] = useState( existingTokens );
const setTokens = ( token ) => {
localStorage.setItem( 'token', JSON.stringify( token ) );
setAuthTokens( token );
};
return (
<AuthContext.Provider value={{ authTokens, setAuthTokens: setTokens }}>
<BrowserRouter>
<Switch>
<PublicRoute exact path='/' component={ Logon } />
<PublicRoute exact path='/register' component={ Register } />
<PublicRoute exact path='/register/ong' component={ Ong } />
<PublicRoute exact path='/register/user' component={ User } />
<PrivateRoute exact path='/administration' component={ Admin } />
<PrivateRoute exact path='/profile' component={ Profile } />
<PrivateRoute exact path='/incidents/new' component={ NewIncident } />
</Switch>
</BrowserRouter>
</AuthContext.Provider>
)
};
2个回答
isAuthenticated
是一个异步函数,因此您必须等待结果才能使用它。但情况比这更复杂。您的
PublicRoute
函数是一个
组件
,并且组件必须同步返回您想要呈现的内容(至少在我们获得悬念之前)。由于
isAuthenticated
是异步的,这意味着您必须渲染两次:一次是在确定
isAuthenticated
的结果时,然后再次渲染。最简单的方法是使用状态:
import { useEffect, useState } from 'react';
function PublicRoute( { component: Component, ...rest } ) {
const { authTokens } = useAuth();
const [isAuthenticated, setIsAuthenticated] = useState(null);
useEffect(() => {
isAuthenticated(authTokens).then(setIsAuthenticated);
async function isAuthenticated(token) {
if ( token === undefined ) return false;
try {
const response = await api.post( '/cT', { token } );
return response.status === 200;
} catch ( error ) {
console.log( 'Retorned false with error.' );
console.log( error );
return false;
};
}
}, [authTokens]);
console.log( 'Is authenticated?' );
console.log( isAuthenticated ); // Will be null (unknown), true, or false
if (isAuthenticated === null) {
// Render nothing for now; component will re-render after auth check
return null;
}
return (
<Route { ...rest }
render={
( props ) => ( isAuthenticated ) ?
( <Redirect to='/profile' /> ) :
( <Component { ...props } /> )
}
/>
);
}
您的组件现在返回 React 可以处理的内容而不是 Promise,并且它通过重新渲染来处理异步性。您的下一个重点应该是“用户在等待时应该看到什么?”这种采用的方法是返回
null
,因此路由不会暴露,但您可能需要考虑渲染微调器,这可能需要将此身份验证检查功能移动到组件树中的其他位置。
Jacob
2020-04-15
async
始终与
await
关键字配对:
const estaAutenticado = await isAuthenticated( authTokens );
^^^^^
现在您可以在
estaAutenticado
中访问该值。
moonwave99
2020-04-14