reactjs React导航路由器v6无效挂钩调用

qfe3c7zg  于 2023-01-17  发布在  React
关注(0)|答案(5)|浏览(177)

我试图重定向我的用户时,用户登录。但我所有的方法,我发现到目前为止不会工作。etg我试图使用使用导航功能使用React路由器v6。
但由于某种原因,我得到以下错误:

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();

功能:

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" />;
      }
    })
  }
}

问:我必须做什么才能修复此问题并能够重定向我的用户?

2eafrhcq

2eafrhcq1#

编辑:对于React路由器v6

在react-router v6中没有withRouteruseHistory,为了简单起见,我建议重构您的组件以使用钩子,但另一种解决方案是创建一个 Package 器组件,将从钩子获得的导航函数作为prop传递:

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,所以您不能在那里使用钩子。
另一种可行的方法是将组件 Package 在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将把历史作为一个 prop 注入。

vbkedwbf

vbkedwbf2#

在react-router-dom最新**版本(v6)**中,您不能使用this.props.match.params.idthis.props.history(在react最新版本中,将history替换为navigate)。此外,您不能在类组件中调用它们。要在类组件中调用它们,请先创建一个函数-

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

    export function withParamsAndNavigate(Component) {
      return (props) => (
       <Component {...props} params={useParams()} navigate={useNavigate()} />
  );
}
  • 我想把它用在ProductDetails组件上。如下所示-
import { withParamsAndNavigate } from "./getParamsAndNavigate.js";

 class ProductDetails extends React.Component {
  state = {//}

render() {
 const{params,navigate} = this.props;
  // params.id - will return the id,
  // navigate('yourUrl') - will redirect the target url.
  return (
     //
   );
  }
 }

export default withParamsAndNavigate(ProductDetails);
  • 这是我的App模块,我在其中定义了路由-
import React from "react";
     import { Routes, Route} from "react-router-dom";
     import Product from "./components/Product";
     import ProductDetails "./components/ProductDetails";

     function App() {
       return (
           <div>
              <main role='main' className='container'>
                <Routes>
                   <Route path='/product' element={<Product />} />
                   <Route path="/product/:id"} element={<ProductDetails />} />
                </Routes>
              </main>
          </div>
       );
      }
     export default App;
  • 对我很有效,希望对你有帮助。
vfhzx4xs

vfhzx4xs3#

您只能在组件内部的顶层(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" />;
        }
        
        
      })
              
  
        }
        
        
  }

注意:你必须直接在你的组件本身中完成,你不能在一个不是组件的普通函数中使用钩子。

n8ghc7c1

n8ghc7c14#

*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;
balp4ylt

balp4ylt5#

在普通函数中不使用useNavigate()

相关问题