成功登录后导航到其他页面

时间:2020-02-04 11:25:50

标签: reactjs react-hooks react-router-dom

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"

2 个答案:

答案 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

您需要做的是将authHandlerhistory.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 (...)
}