繁体   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