App.tsx
import React from 'react';
import {
BrowserRouter as Router,
Redirect,
Route,
Switch
} from 'react-router-dom';
import './app.css';
import Login from './auth/pages/login';
import DashBoard from './dashboard/dashboard';
export const App = () => {
return (
<div className="app">
<Router>
<Switch>
<Route path="/auth/login" component={Login} />
<Route path="/dashboard" component={DashBoard} />
<Redirect from="/" exact to="/auth/login" />
</Switch>
</Router>
</div>
);
};
export default App;
login.tsx
import { useHistory } from 'react-router-dom';
const authHandler = async (email, password) => {
const history = useHistory();
try {
const authService = new AuthService();
await authService
.login({
email,
password
})
.then(() => {
history.push('/dashboard');
});
} catch (err) {
console.log(err);
}
};
从上面的代码中,我试图在成功登录后导航至仪表板。 单击提交按钮后,将调用auth处理函数。 登录详细信息已成功通过authhandler函数获取,但是一旦使用历史记录进行导航,就会出现以下错误
"Uncaught (in promise) Error: Invalid hook call. Hooks can only be called inside of the body of a function component"
答案 0 :(得分:1)
错误文字非常清楚。您不能在功能组件之外调用UIView
或任何其他挂钩。同样,必须在组件顶部无条件调用钩子。尝试在实际组件内部调用override func viewDidLoad() {
super.viewDidLoad()
collectionView.dataSource = self
collectionView.delegate = self
let layout:UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 10, right: 5)
collectionView.collectionViewLayout = layout
}
extension LobbyViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = UIScreen.main.bounds.size.width
return CGSize(width: ((width / 2)), height: 150)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
}
,并将useHistory
作为参数传递给useHistory
。
答案 1 :(得分:1)
问题在于authHandler
是一个异步函数,在“正常”函数中使用钩子不起作用。它会破坏rule of hooks。
您需要做的是将authHandler
和history.push('/dashboard')
分开。
您可以做的是返回异步请求,然后使用.then
来调用history.push
。
const authHandler = async (email, password) => {
const authService = new AuthService();
// returning the request
return await authService
.login({
email,
password
})
};
在组件内部,您使用useHistory
钩子并在执行某些操作时调用authHandler
。
const MyComponent = () => {
const history = useHistory()
const onClick = (email, password) => {
authHandler(email, password)
.then(() => history.push('/dashboard'))
}
return (...)
}