我如何在 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:
- You might have mismatching versions of React and the renderer (such as React DOM)
- You might be breaking the Rules of Hooks
- 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?
我是 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:
- You might have mismatching versions of React and the renderer (such as React DOM)
- You might be breaking the Rules of Hooks
- 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?