React中传递变量作为Prop始终保持初始值的问题解决
React数学测验分数传递问题解决方案
问题描述
我正在编写一个包含Index、Quiz、Results三个组件的React数学测验程序。点击Quiz组件的分析按钮后,统计正确答案数量并跳转到Results页面,但无论选对多少题,Results组件的score props始终是totalCorrect的初始值0。
原因分析
- 普通变量不触发重渲染:
totalCorrect是普通let变量,修改它不会触发Index组件重新渲染,因此Routes里的Results组件一直使用初始值0。 - 页面刷新重置状态:使用
window.location = "/results"会导致整个页面刷新,应用重新加载,totalCorrect被重置为初始值。 - 直接操作DOM不符合React理念:通过
document.getElementsByTagName获取输入值绕开了React的状态管理,容易导致数据流不一致。
解决方案
方案一:React状态+路由导航钩子(推荐)
步骤1:修改Index组件
使用useState管理分数状态,用useNavigate实现无刷新跳转,同时整合答案验证逻辑:
import { useState, useNavigate } from 'react'; import { BrowserRouter, Routes, Route } from 'react-router-dom'; import Quiz from './Quiz'; import Results from './Results'; function Index() { const [totalCorrect, setTotalCorrect] = useState(0); const navigate = useNavigate(); const analyzeAnswers = (selectedAnswers) => { // 预设各题正确答案 const correctAnswers = { q1: "correct", q2: "correct", q3: "correct" }; let score = 0; // 遍历用户选中的答案,统计正确数量 Object.entries(selectedAnswers).forEach(([q, ans]) => { if (ans === correctAnswers[q]) score++; }); setTotalCorrect(score); navigate('/results'); }; return ( <div> <BrowserRouter> <Routes> <Route path="/" element={<Quiz onAnalyze={analyzeAnswers} />} /> <Route path="/results" element={<Results score={totalCorrect} />} /> </Routes> </BrowserRouter> </div> ); } export default Index;
步骤2:修改Quiz组件
用React状态管理用户选中的答案,避免直接操作DOM,将选中结果传递给分析函数:
import { useState } from 'react'; function Quiz({ onAnalyze }) { const [selectedAnswers, setSelectedAnswers] = useState({ q1: '', q2: '', q3: '' }); const handleAnswerChange = (e) => { const { name, value } = e.target; setSelectedAnswers(prev => ({ ...prev, [name]: value })); }; return ( <div> <p>What is 2 + 2?</p> <input type="radio" name="q1" value="correct" checked={selectedAnswers.q1 === "correct"} onChange={handleAnswerChange} /> 4<br /> <input type="radio" name="q1" value="5" checked={selectedAnswers.q1 === "5"} onChange={handleAnswerChange} /> 5<br /> <input type="radio" name="q1" value="3" checked={selectedAnswers.q1 === "3"} onChange={handleAnswerChange} /> 3<br /> <input type="radio" name="q1" value="6" checked={selectedAnswers.q1 === "6"} onChange={handleAnswerChange} /> 6<br /> <p>What is 2 + 3?</p> <input type="radio" name="q2" value="4" checked={selectedAnswers.q2 === "4"} onChange={handleAnswerChange} /> 4<br /> <input type="radio" name="q2" value="correct" checked={selectedAnswers.q2 === "correct"} onChange={handleAnswerChange} /> 5<br /> <input type="radio" name="q2" value="3" checked={selectedAnswers.q2 === "3"} onChange={handleAnswerChange} /> 3<br /> <input type="radio" name="q2" value="6" checked={selectedAnswers.q2 === "6"} onChange={handleAnswerChange} /> 6<br /> <p>What is 2 + 4?</p> <input type="radio" name="q3" value="4" checked={selectedAnswers.q3 === "4"} onChange={handleAnswerChange} /> 4<br /> <input type="radio" name="q3" value="5" checked={selectedAnswers.q3 === "5"} onChange={handleAnswerChange} /> 5<br /> <input type="radio" name="q3" value="3" checked={selectedAnswers.q3 === "3"} onChange={handleAnswerChange} /> 3<br /> <input type="radio" name="q3" value="correct" checked={selectedAnswers.q3 === "correct"} onChange={handleAnswerChange} /> 6<br /> <br /> <button onClick={() => onAnalyze(selectedAnswers)}>analyze</button> </div> ); } export default Quiz;
步骤3:Results组件保持不变
function Results({ score }) { return <p>You got {score} correct!</p>; } export default Results;
方案二:路由State传递分数
如果不想在Index组件中维护分数状态,可以通过路由的state直接传递分数:
修改Index组件的分析函数
const analyzeAnswers = (selectedAnswers) => { const correctAnswers = { q1: "correct", q2: "correct", q3: "correct" }; let score = 0; Object.entries(selectedAnswers).forEach(([q, ans]) => { if (ans === correctAnswers[q]) score++; }); // 跳转时将分数存入路由state navigate('/results', { state: { score } }); };
修改Results组件获取路由state
import { useLocation } from 'react-router-dom'; function Results() { const location = useLocation(); // 从路由state中取分数,默认值为0 const score = location.state?.score || 0; return <p>You got {score} correct!</p>; } export default Results;
内容的提问来源于stack exchange,提问作者DennisM
相关产品推荐
相关产品推荐

