我如何在 reactJS 中导航到其他组件

How can I navigate to other component here in reactJS

我是 React JS 的新手,我在这段代码中收到无效挂钩调用的错误。 错误信息是:

Uncaught 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

由于这个错误,我的 API 不是 运行。 这个 HandleLogin 函数在一个单独的文件中,我正在将这个函数导入到受保护的 routes.js 文件中 我的代码是:

function HandleLogin() {
    const navigate = useNavigate() // it gives me the error
    return (e, data) => {
            e.preventDefault();
            fetch('http://localhost:8000/token-auth/', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(data)
            })
                .then(res => res.json())
                .then(json => {
                    localStorage.setItem('token', json.token);
                    username = json.user.username
                    if (json.email === 'admin@gmail.com')
                        navigate('/admindb')
                    else
                        navigate('/userdb')
                })
                .catch((res) => document.getElementById('text-error').innerHTML = res.error)
        }
}

我用谷歌搜索了一下,我们不能在回调函数中使用钩子,所以我把它放在 HandleLogin 函数返回的函数之外,但它仍然给出这个错误。

我想知道我做错了什么,以及如何解决它。

我在我的路线中使用 HandleLogin,如下所示:

<Route exact path="/login" name="Login Page" element={<Login handle_login={HandleLogin} />} />

这是我的 Login.js 文件:

function Login(props) {
  const [username, setUsername] = useState('')
  const [password, setPassword] = useState('')
  //const [logged_in, setLogged_in] = useState(localStorage.getItem('token') ? true : false);
  return (
    <div className="bg-light min-vh-100 d-flex flex-row align-items-center">
      {/* <div>{props.myname}</div> */}
      <CContainer>
        <CRow className="justify-content-center">
          <CCol md={8}>
            <CCardGroup>
              <CCard className="p-4">
                <CCardBody>
                  // here I'm calling handle_login 
                  <CForm onSubmit={(e)=>props.handle_login(e,{username,password})}>
                    <h1>Login</h1>
                    <p className="text-medium-emphasis">Sign In to your account</p>
                    <CInputGroup className="mb-3">
                      <CInputGroupText>
                        <CIcon icon={cilUser} />
                      </CInputGroupText>
                      <CFormInput id="username" type="text" placeholder="Username" autoComplete="username"
                          value={username} onChange={e => setUsername(e.target.value)} required />
                    </CInputGroup>
                    <CInputGroup className="mb-4">
                      <CInputGroupText>
                        <CIcon icon={cilLockLocked} />
                      </CInputGroupText>
                      <CFormInput
                        id="password"
                        type="password"
                        placeholder="Password"
                        autoComplete="current-password"
                        value={password}
                        onChange={e => setPassword(e.target.value)}
                        required
                      />
                    </CInputGroup>
                    <CRow>
                      <CCol xs={6}>
                        <CButton type="submit" color="primary" className="px-4">
                          Login
                        </CButton>
                      </CCol>
                      <CCol xs={6} className="text-right">
                        <Link to="/verifyEmail" color="link" className="px-0">
                          Forgot password?
                        </Link>
                      </CCol>
                    </CRow>
                    <CFormFeedback className='text-danger' id='text-error'></CFormFeedback>
                  </CForm>
                </CCardBody>
              </CCard>
              <CCard className="text-white bg-primary py-5" style={{ width: '44%' }}>
                <CCardBody className="text-center">
                  <div>
                    <h2>Sign up</h2>
                    <p>
                      Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
                      tempor incididunt ut labore et dolore magna aliqua.
                    </p>
                    <Link to="/register">
                      <CButton color="primary" className="mt-3" active tabIndex={-1}>
                        Register Now!
                      </CButton>
                    </Link>
                  </div>
                </CCardBody>
              </CCard>
            </CCardGroup>
          </CCol>
        </CRow>
      </CContainer>
    </div>
  )
}

我的 App.js 文件:

import React, { useEffect } from 'react'
import { HashRouter, Navigate, Outlet, Route, Routes, useNavigate } from 'react-router-dom'
import Home from './views/Pages/Home'
import './scss/style.scss'
// import Register from './views/Pages/Register'
import VerifyEmail from './views/Pages/VerifyEmail'
import ValidateCode from './views/Pages/ValidateCode'
import ChangePassword from './views/Pages/ChangePassword'
import AdminDashboard from './views/Pages/AdminDashboard'
import UserDashboard from './views/Pages/UserDashboard/UserDashboard'

const loading = (
  <div className="pt-3 text-center">
    <div className="sk-spinner sk-spinner-pulse"></div>
  </div>
)

// Pages
const Login = React.lazy(() => import('./views/Pages/Login'))
const Register = React.lazy(() => import('./views/Pages/Register'))

let username = ''

const App = ()=> {
  const navigate = useNavigate()

  function handleLogin() {
    return (e, data) => {
      e.preventDefault();
      fetch('http://localhost:8000/token-auth/', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(data)
      })
        .then(res => res.json())
        .then(json => {
          localStorage.setItem('token', json.token);
          username = json.user.username
          if (json.email === 'admin@gmail.com')
            navigate('/admindb')
          else
            //<Navigate to='/userdb' />
            navigate('/userdb')
        })
        .catch((res) => document.getElementById('text-error').innerHTML = res.error)
    }
  }

  return (
    <HashRouter>
      <React.Suspense fallback={loading}>
        <Routes>
          <Route exact path="/" name="Home Page" element={<Home />} />
          <Route exact path="/login" name="Login Page" element={<Login handle_login={handleLogin} />} />
          <Route exact path="/register" name="Register Page" element={<Register />} />
          <Route exact path="/verifyEmail" name="Email verification Page" element={<VerifyEmail />} />
          <Route exact path="/verifyItsYou" name="Code verification Page" element={<ValidateCode />} />
          <Route exact path="/changePassword" name="Change password Page" element={<ChangePassword />} />
          <Route exact path="/admindb" name="Admin Dashboard Page" element={<AdminDashboard />} />
          <Route exact path="/userdb" name="User dashboard Page" element={<UserDashboard />} />
        </Routes>
      </React.Suspense>
    </HashRouter>

  )
}

export default App

React 挂钩只能从 React 函数和自定义挂钩中调用。它们不能在回调中调用。将 useNavigate 挂钩调用 移出 回调,并移至呈现路由的主要组件主体中。您还需要将 移动 handleLogin 回调 父组件中,以便它可以访问 in-scope navigate函数。

示例:

const App = () => {
  const navigate = useNavigate();

  ...

  function handleLogin() {
    return (e, data) => {
      e.preventDefault();
      fetch('http://localhost:8000/token-auth/', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(data)
      })
        .then(res => res.json())
        .then(json => {
          localStorage.setItem('token', json.token);
          username = json.user.username;
          navigate(json.email === 'admin@gmail.com'
            ? '/admindb'
            : '/userdb'
          );
        })
        .catch((res) => {
          document.getElementById('text-error').innerHTML = res.error;
        });
    }
  }

  return (
    <React.Suspense fallback={loading}>
      <Routes>
        <Route path="/" name="Home Page" element={<Home />} />
        <Route path="/login" name="Login Page" element={<Login handle_login={handleLogin} />} />
        <Route path="/register" name="Register Page" element={<Register />} />
        <Route path="/verifyEmail" name="Email verification Page" element={<VerifyEmail />} />
        <Route path="/verifyItsYou" name="Code verification Page" element={<ValidateCode />} />
        <Route path="/changePassword" name="Change password Page" element={<ChangePassword />} />
        <Route path="/admindb" name="Admin Dashboard Page" element={<AdminDashboard />} />
        <Route path="/userdb" name="User dashboard Page" element={<UserDashboard />} />
    </Routes>
  </React.Suspense>
  );
}

export default App;

HashRouter 包裹在 App 组件周围:

<HashRouter>
  <App />
</HashRouter?