簡體   English   中英

React 導航路由器 v6 無效掛鈎調用

[英]React navigate router v6 invalid hook call

我試圖在用戶登錄時重定向我的用戶。但我到目前為止發現的所有方法都不起作用。 etg 我正在嘗試使用 react router v6 使用 useNavigate function。

但由於某種原因,我收到以下錯誤:

Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See react-invalid-hook-call for tips about how to debug and fix this problem.

在:

/login.jsx:35
let navigate = useNavigate();

function:

PerformLogin = () => {
  let navigate = useNavigate();
  const username = this.state.username;
  const password = this.state.password;
  if (username === '') {
    console.log("please enter username");
  } else if (password === '') {
    console.log("please enter password");
  } else {
    console.log("username of login: ",this.state.username);
    axios.post(process.env.REACT_APP_DATAURL + `/login`,{ username: username, password: password },{withCredentials: true})
    .then(res => {
      res = res.data;
      console.log(res);
      console.log(res.data);
      if (res.type) {
        console.log("navigating logged in");
        navigate.push('/crime');
        //return <Navigate to="/crime" />;
      }
    })
  }
}

問:我該怎么做才能解決此問題並能夠重定向我的用戶?

編輯:對於反應路由器 v6

在 react-router v6 中沒有withRouteruseHistory 為了簡單起見,我建議重構您的組件以使用鈎子,但另一種解決方案是創建一個包裝器組件,它將從鈎子中獲得的導航函數作為道具傳遞:

import { useNavigate } from 'react-router-dom';

class MyComponent extends React.Component {
  //...
    PerformLogin = () => {
        const username = this.state.username;
        const password = this.state.password;
        // ...
        this.props.navigate('/crime');
    }
}

function WithNavigate(props) {
    let navigate = useNavigate();
    return <MyComponent {...props} navigate={navigate} />
}

export default WithNavigate

useHistory是一個鈎子,鈎子只能在“函數”組件中使用。

但是我猜你是從“類”組件中使用它的,因為有一些this.state ,所以你不能在那里使用鈎子。

另一種適合您的方法是將您的組件包裝在withRouter

import { withRouter } from "react-router";

class MyComponent extends React.Component {
  //...
    PerformLogin = () => {
        const history = this.props.history;
        const username = this.state.username;
        const password = this.state.password;
        // ...
    }
}

export default withRouter(MyComponent)

withRouter 將歷史作為道具注入。

您只能在組件內調用頂層 ( https://reactjs.org/docs/hooks-rules.html ) 的鈎子。

因此,這是無效的,因為它不僅在 if 語句中,在 promise 的.then函數中,而且似乎甚至不是函數組件,而只是一個函數:

if (res.type) {
        console.log("navigating logged in");
        navigate.push('/crime');
        //return <Navigate to="/crime" />;
    }

我會嘗試做一些類似設置標志的事情,然后根據該標志進行導航:

  PerformLogin = () => {
        let navigate = useNavigate();
        let shouldNavigate = false;
        const username = this.state.username;
        const password = this.state.password;
        if (username === '') {
            console.log("please enter username");
        } else if (password === '') {
            console.log("please enter password");
        } else {
                  console.log("username of login: ",this.state.username);
                   axios.post(process.env.REACT_APP_DATAURL + `/login`,{ username: username, password: password },{withCredentials: true})
      .then(res => {
          res = res.data;
        console.log(res);
        console.log(res.data);
        if (res.type) {
            console.log("navigating logged in");
            shouldNavigate = true;
            //return <Navigate to="/crime" />;
        }
        
        
      })
              
  
        }
        
        navigate.push(shouldNavigate ? '/crime' : currentURL);
  }

但我會完全避免這種情況,只需利用 useHistory 鈎子來獲取歷史實例並對其進行處理(我也沒有測試過,但它應該可以工作):

  PerformLogin = () => {
        const history = useHistory();
        const username = this.state.username;
        const password = this.state.password;
        if (username === '') {
            console.log("please enter username");
        } else if (password === '') {
            console.log("please enter password");
        } else {
                  console.log("username of login: ",this.state.username);
                   axios.post(process.env.REACT_APP_DATAURL + `/login`,{ username: username, password: password },{withCredentials: true})
      .then(res => {
          res = res.data;
        console.log(res);
        console.log(res.data);
        if (res.type) {
            console.log("navigating logged in");
            history.push('/crime');
            //return <Navigate to="/crime" />;
        }
        
        
      })
              
  
        }
        
        
  }

注意:您必須直接在組件本身中執行此操作,不能在非組件的普通函數中使用鈎子。

你不在普通函數中使用useNavigate()

在此處輸入圖片說明

import { useParams,useNavigate } from "react-router-dom";

class MyComponent 擴展 React.Component { // }

導出函數 withParamsAndNavigate(MyComponent) { return (props) =>( <MyComponent {...props} params={useParams()} navigate={useNavigate()} />); }

** const { params, navigation } = this.props;**這是 react-router-dom 最新版本

*An example of how you can use.useHsitory has not been working properly in v6

import React from 'react';
import { createBrowserHistory } from 'history';


const StatusCodeCat: React.FC = () => {
//   const history = useHistory();
  const hsitory = createBrowserHistory();
  console.log(hsitory);
  


  return (
    <div>
        never
    </div>
  );
}

export default StatusCodeCat;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM