SolidJS Router useNavigate() throws: Error: Make sure your app is wrapped in a <Router />
SolidJS Router useNavigate() throws: Error: Make sure your app is wrapped in a <Router />
即使我的应用程序包含在 Router 标记中,当我使用 useNavigate()
或 <Navigate />
元素时,我也会遇到相同的错误 login.tsx:27 Error: Make sure your app is wrapped in a <Router />
这是我的 index.tsx
/* @refresh reload */
import { render } from 'solid-js/web';
import './index.css';
import App from './App';
import { Router } from 'solid-app-router';
render(
() => (
<Router>
<App />
</Router>
),
document.getElementById('root') as HTMLElement
)
App.tsx
const App: Component = () => {
return (
<>
<Routes>
<Route path="/" component={Landing} />
<Route path="/dashboard" component={Dashboard} />
</Routes>
</>
)
}
作为登录组件父级的登陆组件
import { useNavigate } from 'solid-app-router'
import { Component, createSignal, Show, onMount } from 'solid-js'
import { getIsValidSession } from '../services/session'
import '../styling/landing.css'
import CreateAccount from './landing/create-account'
import Login from './landing/login'
const Landing: Component = () => {
const [displayLogin, setDisplayLogin] = createSignal(true)
return (
<div class="landing text-center">
<main class="form-signin">
<img
class="mb-4"
src="src/assets/original/tracker-image.png"
alt=""
width="72"
height="85"
/>
<Show when={displayLogin()} fallback={<CreateAccount />}>
<Login />
</Show>
<Show
when={displayLogin()}
fallback={
<button
class="w-100 btn btn-lg btn-primary mt-3"
onClick={toggleDisplay}>
Login Existing User
</button>
}>
<button
class="w-100 btn btn-lg btn-primary mt-3"
onClick={toggleDisplay}>
Create Account
</button>
</Show>
</main>
</div>
)
}
export default Landing
和登录组件
import { useNavigate } from 'solid-app-router'
import { Component, createSignal } from 'solid-js'
import Response from '../../models/response'
import { PostSession, Session } from '../../models/session'
import * as session from '../../services/session'
const Login: Component = () => {
const [email, setEmail] = createSignal('')
const [password, setPassword] = createSignal('')
const login = async (event: any) => {
event.preventDefault()
try {
console.log(`Login: ${email()}, Password: ${password()}`)
const res = await session.login({
email: email(),
password: password(),
} as PostSession)
if (res.status !== 200) {
window.alert('Login failed')
} else {
const navigate = useNavigate()
navigate('/dashboard', { replace: true })
}
} catch (error) {
console.error(error)
}
}
return (
<form>
<h1 class="h3 mb-3 fw-normal">Please sign in</h1>
<div class="form-floating">
<input
type="email"
class="form-control"
id="floatingInput"
placeholder="name@example.com"
value={email()}
onChange={(e: any) => setEmail(e.target.value)}
/>
<label for="floatingInput">Email address</label>
</div>
<div class="form-floating">
<input
type="password"
class="form-control"
id="floatingPassword"
placeholder="Password"
value={password()}
onChange={(e: any) => setPassword(e.target.value)}
/>
<label for="floatingPassword">Password</label>
</div>
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me" /> Remember me
</label>
</div>
<button
class="w-100 btn btn-lg btn-primary"
onClick={e => login(e)}>
Sign in
</button>
</form>
)
}
export default Login
为我的用例设置路由器的正确方法是什么?
这里的问题(我认为)是您在事件处理程序中使用 useNavigate()
。该函数需要在渲染期间“在树内”同步调用,而不是在不具有相同执行上下文的回调中调用。试试这个:
const [email, setEmail] = createSignal('')
const [password, setPassword] = createSignal('')
const navigate = useNavigate()
然后像以前一样在您的事件处理程序中使用它:
} else {
navigate('/dashboard', { replace: true })
}
这样行吗?
即使我的应用程序包含在 Router 标记中,当我使用 useNavigate()
或 <Navigate />
元素时,我也会遇到相同的错误 login.tsx:27 Error: Make sure your app is wrapped in a <Router />
这是我的 index.tsx
/* @refresh reload */
import { render } from 'solid-js/web';
import './index.css';
import App from './App';
import { Router } from 'solid-app-router';
render(
() => (
<Router>
<App />
</Router>
),
document.getElementById('root') as HTMLElement
)
App.tsx
const App: Component = () => {
return (
<>
<Routes>
<Route path="/" component={Landing} />
<Route path="/dashboard" component={Dashboard} />
</Routes>
</>
)
}
作为登录组件父级的登陆组件
import { useNavigate } from 'solid-app-router'
import { Component, createSignal, Show, onMount } from 'solid-js'
import { getIsValidSession } from '../services/session'
import '../styling/landing.css'
import CreateAccount from './landing/create-account'
import Login from './landing/login'
const Landing: Component = () => {
const [displayLogin, setDisplayLogin] = createSignal(true)
return (
<div class="landing text-center">
<main class="form-signin">
<img
class="mb-4"
src="src/assets/original/tracker-image.png"
alt=""
width="72"
height="85"
/>
<Show when={displayLogin()} fallback={<CreateAccount />}>
<Login />
</Show>
<Show
when={displayLogin()}
fallback={
<button
class="w-100 btn btn-lg btn-primary mt-3"
onClick={toggleDisplay}>
Login Existing User
</button>
}>
<button
class="w-100 btn btn-lg btn-primary mt-3"
onClick={toggleDisplay}>
Create Account
</button>
</Show>
</main>
</div>
)
}
export default Landing
和登录组件
import { useNavigate } from 'solid-app-router'
import { Component, createSignal } from 'solid-js'
import Response from '../../models/response'
import { PostSession, Session } from '../../models/session'
import * as session from '../../services/session'
const Login: Component = () => {
const [email, setEmail] = createSignal('')
const [password, setPassword] = createSignal('')
const login = async (event: any) => {
event.preventDefault()
try {
console.log(`Login: ${email()}, Password: ${password()}`)
const res = await session.login({
email: email(),
password: password(),
} as PostSession)
if (res.status !== 200) {
window.alert('Login failed')
} else {
const navigate = useNavigate()
navigate('/dashboard', { replace: true })
}
} catch (error) {
console.error(error)
}
}
return (
<form>
<h1 class="h3 mb-3 fw-normal">Please sign in</h1>
<div class="form-floating">
<input
type="email"
class="form-control"
id="floatingInput"
placeholder="name@example.com"
value={email()}
onChange={(e: any) => setEmail(e.target.value)}
/>
<label for="floatingInput">Email address</label>
</div>
<div class="form-floating">
<input
type="password"
class="form-control"
id="floatingPassword"
placeholder="Password"
value={password()}
onChange={(e: any) => setPassword(e.target.value)}
/>
<label for="floatingPassword">Password</label>
</div>
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me" /> Remember me
</label>
</div>
<button
class="w-100 btn btn-lg btn-primary"
onClick={e => login(e)}>
Sign in
</button>
</form>
)
}
export default Login
为我的用例设置路由器的正确方法是什么?
这里的问题(我认为)是您在事件处理程序中使用 useNavigate()
。该函数需要在渲染期间“在树内”同步调用,而不是在不具有相同执行上下文的回调中调用。试试这个:
const [email, setEmail] = createSignal('')
const [password, setPassword] = createSignal('')
const navigate = useNavigate()
然后像以前一样在您的事件处理程序中使用它:
} else {
navigate('/dashboard', { replace: true })
}
这样行吗?