React中if/else结合useNavigate跳转页面失效问题求助
问题描述
在React.js中使用if/else语句实现页面跳转时遇到问题,尝试通过React Router的useNavigate钩子,根据用户问卷答案跳转到对应健康需求页面,但提交后要么无反应,要么出现意外令牌错误。
测试用例
- 描述:用户填写问卷并提交后,应跳转至符合其健康需求的专属页面。
- 步骤1:用户填写表单
- 预期:可查看用户选择的答案
- 实际:正常显示所选答案
- 步骤2:用户点击提交
- 预期:跳转至对应运动选项页面
- 实际:无反应或出现意外令牌错误
错误异常
反复收到提示:[Intervention] Slow network is detected. Fallback font will be used while loading: chrome-extension://liecbddmkiiihnedobmlmillhodjkdmb/fonts/CircularXXWeb-Book.woff2,已尝试重启电脑但无效,询问该提示是否会影响代码。
问题代码
App.js
import React, { useState } from 'react'; import Introduction from './components/introduction'; import Questions from './components/beginning'; import Male from './components/questions'; import { BrowserRouter as Router, Route, Routes } from 'react-router-dom'; export default function App() { return ( //Revisit <Route path="/questions" element= {<Male />} /> for Readability!! <Router> <Routes> <Route path= "/" element={<Introduction />} /> <Route path="/beginning" element= {<Questions />} /> <Route path="/personalExercise" element={<personalExercise/>} /> <Route path="/questions" element= {<Male />} /> </Routes> </Router> ); }
index.js
import ReactDOM from "react-dom/client"; import App from "./App"; const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<App />)
Questions.js(问卷组件)
import React, { useState } from 'react'; import Form from 'react-bootstrap/Form'; import { useNavigate } from 'react-router-dom'; export default function Questions(props) { const navigate = useNavigate() const[formData, setFormData] = useState({ gender: "", userAge: "", goals:"", }); function handleChange(event) { const { name, value, type, checked } = event.target; setFormData(prevFormData => { return { ...prevFormData, [name]: type === 'checkbox' ? checked : value }; }); } function handleSubmit(event) { event.preventDefault() navigate(getPath()) }; const getPath = () => { if(formData.gender === "male" && formData.userAge === "Young" && formData.goals === "active"){ return navigate("/beginning") } // switch (formData) { // case { gender: "male", userAge: "young", goals: "active" }: return navigate("../beginning"); // break; // default: // return navigate("/beginning") // } } return ( <> <header>Questions</header> <Form onSubmit={handleSubmit}> <fieldset> <legend>What was your gender at birth</legend> <input type='radio' id = 'male' name = 'gender' value = 'male' checked={formData.gender === "male"} onChange={handleChange} /> <label htmlFor="male"> Male </label> <br /> <input type='radio' id='female' name='gender' value = 'female' checked={formData.gender === "female"} onChange={handleChange} /> <label htmlFor="female"> Female </label> <br /> </fieldset> <fieldset> <legend>How old are you?</legend> <input type='radio' id="young" name="userAge" value="young" checked={formData.userAge === "young"} onChange={handleChange} /> <label htmlFor="young"> 18-28 </label> <br /> <input type='radio' id="middleAged" name="userAge" value="middleAged" checked={formData.userAge === "middleAged"} onChange={handleChange} /> <label htmlFor="middleAged"> 29-39 </label> <br /> <input type='radio' id="older" name="userAge" value="older" checked={formData.userAge === "older"} onChange={handleChange} /> <label htmlFor="older"> 40-50 </label> <br /> <input type='radio' id="senior" name="userAge" value="senior" checked={formData.userAge === "senior"} onChange={handleChange} /> <label htmlFor="senior"> 51+ </label> <br /> </fieldset> <br /> <fieldset> <legend>What kind of fitness would you prefer?</legend> <input type="radio" id="active" name="goals" value="active" checked = {formData.goals === "active"} onChange={handleChange} /> <label htmlFor='active'>To stay active!</label> <br /> <input type="radio" id="weight" name="goals" value= "weight" checked = {formData.goals === "weight"} onChange={handleChange} /> <label htmlFor="weight"> To loose weight</label> </fieldset> <br /> <button>Submit</button> </Form> </> ) }
beginning.js(起始页面组件)
import React from 'react'; import {NavLink} from 'react-router-dom' import 'bootstrap/dist/css/bootstrap.min.css' export default function beginning() { return ( <> <p>Before beginning, would you mind entering some info about yourself? This information is used to help understand what kind of exercises suit you and lets the app know how it can fit the 30 min sessions in your day! </p> <p>If you would like to skip the questionnaire and dive right into exercising, so you can personally select what you want as your exercise, that is also an excellent choice! </p> <NavLink to="/questions"> <button>Take Questionnaire</button> </NavLink> <NavLink to="/exercise"> <button>Skip Questionnaire</button> </NavLink> </> ) }
问题修复方案
1. 修正getPath函数逻辑
当前getPath直接在内部调用navigate,导致handleSubmit里的navigate(getPath())相当于重复调用,且getPath返回的是navigate的返回值(undefined),引发跳转异常。应让getPath返回路径字符串,由handleSubmit统一调用navigate:
const getPath = () => { if(formData.gender === "male" && formData.userAge === "young" && formData.goals === "active"){ return "/beginning"; } // 其他条件分支补充... // 默认跳转路径 return "/beginning"; }
2. 修复大小写不匹配问题
表单中userAge的选项值是小写的"young",但原判断里用的是大写开头的"Young",导致条件永远不成立,修改为一致的小写:
if(formData.gender === "male" && formData.userAge === "young" && formData.goals === "active"){...}
3. 组件命名必须首字母大写
React规定组件名称必须首字母大写,否则会被解析为HTML原生标签,引发意外令牌错误。修改beginning.js的组件名称:
export default function Beginning() { // 首字母大写 // ... 内容不变 }
同时在App.js中修正导入和路由配置:
// 修正导入 import Beginning from './components/beginning'; import Questions from './components/questions'; // 修正路由 <Route path="/beginning" element={<Beginning />} /> <Route path="/questions" element={<Questions />} />
4. 关于网络提示的说明
那个慢网络提示是Chrome浏览器扩展(大概率是某个插件的字体加载延迟)导致的,完全不影响代码逻辑,不需要处理,嫌烦的话可以禁用相关扩展试试。
5. 优化冗余代码(可选)
可以把路由映射规则抽成一个配置对象,替代冗余的if/else或switch,比如:
const routeMap = [ { condition: (data) => data.gender === "male" && data.userAge === "young" && data.goals === "active", path: "/beginning" }, // 其他规则添加... ]; const getPath = () => { const match = routeMap.find(item => item.condition(formData)); return match?.path || "/beginning"; }
内容的提问来源于stack exchange,提问作者user12761285

