React输入内容时变量数组自动变化的问题求助
问题:React数学题组件输入时变量自动变化
我是React新手,正在开发一个简易数学Level组件。为了实现复用性,我希望传入题目中的变量数量(当前为2个),通过variables变量调用GenerateVaribles函数生成变量:
const variables=GenerateVaribles(numOfVariables,min,max)
GenerateVaribles函数代码:
function GenerateVaribles(numOfVariables,min,max){ const variables = []; for (let i = 0; i < numOfVariables; i++) { const value = Math.floor(Math.random() * (max - min + 1)) + min; variables.push(value); } return variables; }
问题现象
每次在输入框中输入内容时,数组内的所有变量都会发生变化。
相关组件代码
输入组件Answer:
function Answer({inputValue,inputValueText,solution,remake,pointsChange,setSolved}){ const handleKeyPress = (event) => { if (event.key === 'Enter') { if(solution== Number(inputValueText)){ console.log("Correct!!!!!!!!") setSolved(1) pointsChange("Add") remake() inputValue("") }else{ setSolved(0) pointsChange("Remove") inputValue("") } } }; const handleInputChange = (event) => { inputValue(event.target.value); }; return( <input value={inputValueText} className="solution" onKeyDown={handleKeyPress} onChange={handleInputChange}/> ) }
完整Level组件代码:
import { useState,useEffect } from 'react' import './App.css' import Timer from './Timer.jsx' function GenerateVaribles(numOfVariables,min,max){ const variables = []; for (let i = 0; i < numOfVariables; i++) { const value = Math.floor(Math.random() * (max - min + 1)) + min; variables.push(value); } return variables; } function Level({solutionTime,digits,numOfVariables}) { const [points, setPoints] = useState(0); const [min,max]=getMax(digits) const variables=GenerateVaribles(numOfVariables,min,max) const [vari1, setVari1] = useState(() => Math.floor(Math.random() * (max - min + 1)) + min); const [vari2, setVari2] = useState(() => Math.floor(Math.random() * (max - min + 1)) + min); const [theSolution, setTheSolution] = useState(GetSolution(variables)); const [inputValue, setInputValue] = useState(''); const [pointsClass, setPointsClass]=useState(""); // 0表示未解决,1表示已解决 const [isSolved,setIsSolved]=useState(0) const generateNewProblem = () => { const newVari1 = Math.floor(Math.random() * (max - min + 1)) + min; const newVari2 = Math.floor(Math.random() * (max - min + 1)) + min; setVari1(newVari1); setVari2(newVari2); setTheSolution(newVari1 + newVari2); }; const handlePointChange=(action,amount=1)=>{ if(action=="Add"){ setPoints(points + amount) } if(action=="Remove"){ setPoints(points - amount) } } const clearValue =()=>{ setInputValue("") } useEffect(() => { },[isSolved]); useEffect(() => { if(points<0){ setPointsClass("negativePoints") }else{ setPointsClass("positivePoints") } },[points]); return ( <> <div className="MainBody"> <Timer time={solutionTime} resetter={isSolved} setSolved={setIsSolved} newProblem={generateNewProblem} pointsChanger={handlePointChange}/> <Problem variablesArray={variables} var1={vari1} var2={vari2} setInputValue={setInputValue} value={inputValue} solution={theSolution} remake={generateNewProblem} points={points} pointsChange={handlePointChange} setSolved={setIsSolved} pointsClass={pointsClass} /> <Button text="Check Solution" solution={theSolution} inputValueText={inputValue} remake={generateNewProblem} clear={clearValue} points={points} setPoints={setPoints} setIsSolved={setIsSolved} /> </div> </> ) } // ----------------------------子组件1----------------------------------- function Problem({variablesArray,var1,var2,setInputValue,value,solution,remake,points,pointsChange,setSolved,pointsClass}){ let html="" for(let i=0;i<variablesArray.length;i++){ html=html+variablesArray[i] if(!(i+1>=variablesArray.length)){ html=html+ "+" } } return( <div className="Problem"> <div className='ProblemHeader'> <span className={"pointsCounter"}>Points:<span className={pointsClass}>{points}</span></span> <Skipper remake={remake}/> </div> <p>{html}={value}</p> <Answer inputValue={setInputValue} inputValueText={value} solution={solution} remake={remake} pointsChange={pointsChange} setSolved={setSolved} /> </div> ) } function Answer({inputValue,inputValueText,solution,remake,pointsChange,setSolved}){ const handleKeyPress = (event) => { if (event.key === 'Enter') { if(solution== Number(inputValueText)){ console.log("Correct!!!!!!!!") setSolved(1) pointsChange("Add") remake() inputValue("") }else{ setSolved(0) pointsChange("Remove") inputValue("") } } }; const handleInputChange = (event) => { inputValue(event.target.value); }; return( <input value={inputValueText} className="solution" onKeyDown={handleKeyPress} onChange={handleInputChange}/> ) }
我期望变量保持不变,直到调用generateNewProblem函数为止(目前还没把数组整合进去,硬编码的vari1、vari2逻辑是正常的)。
解决方案
问题根源
你直接在Level组件的函数体中调用GenerateVaribles生成变量数组:
const variables=GenerateVaribles(numOfVariables,min,max)
React组件每次重新渲染时(比如输入框输入导致inputValue状态更新),这段代码都会重新执行,生成新的随机数组,所以输入时变量会自动变化。而你用useState定义的vari1、vari2不会变,是因为useState的初始化函数只在组件首次渲染时执行一次,后续渲染不会重复执行。
修改步骤
- 将
variables改为组件状态,用useState初始化,确保首次渲染时生成一次; - 更新
generateNewProblem函数,生成新的变量数组并更新状态,同时重新计算答案; - 移除硬编码的
vari1、vari2,统一使用变量数组逻辑。
修改后的核心代码
function Level({solutionTime,digits,numOfVariables}) { const [points, setPoints] = useState(0); const [min,max]=getMax(digits) // 将variables改为state,用初始化函数生成初始值 const [variables, setVariables] = useState(() => GenerateVaribles(numOfVariables,min,max)); // 初始化时计算初始答案 const [theSolution, setTheSolution] = useState(() => variables.reduce((sum, num) => sum + num, 0)); const [inputValue, setInputValue] = useState(''); const [pointsClass, setPointsClass]=useState(""); const [isSolved,setIsSolved]=useState(0) const generateNewProblem = () => { // 生成新的变量数组并更新状态 const newVariables = GenerateVaribles(numOfVariables,min,max); setVariables(newVariables); // 重新计算答案 setTheSolution(newVariables.reduce((sum, num) => sum + num, 0)); }; // ... 其他代码保持不变 }
补充说明
- 用
useState(() => GenerateVaribles(...))的方式,初始化函数只会在组件首次渲染时执行一次,避免每次渲染都生成新数组; - 在
generateNewProblem中更新variables状态时,会触发组件重新渲染,此时新的变量数组会生效,符合你“调用该函数才更新变量”的需求; - 计算答案时用
reduce方法,适配任意数量的变量,实现真正的复用性; - 后续可以移除
vari1、vari2相关的代码,因为已经用数组统一管理变量了。
内容的提问来源于stack exchange,提问作者Kol4o100
相关产品推荐
相关产品推荐

