使用useContext时点击按钮状态变更后React组件不渲染问题
问题原因及修复方案
核心问题:上下文传递的不是响应式状态
你在SectionState中维护了响应式状态questionCtx,但在QuestionContext.Provider的value里传递的是初始化时定义的普通对象newState,而非这个状态变量。这就导致子组件拿到的上下文永远是初始值,哪怕你通过setQuestionCtx更新了状态,上下文也不会同步,自然不会触发Questions组件重新渲染。
额外逻辑问题
- 边界判断错误:
updateQuestion里的currentQuestion > newQuestions.length条件不对,数组索引从0开始,比如4个元素的最大索引是3,应该改成currentQuestion >= newQuestions.length - 1,否则最后一个问题点击Next时会读取数组越界的位置。 - 状态更新依赖旧值:直接使用闭包中的
currentQuestion更新状态可能导致不同步,应该用函数式更新获取最新的状态值。
修复后的SectionState.js
import { React, useState } from 'react' import QuestionContext from './QuestionContext' import questions from '../data/questions.json' const SectionState = (props) => { // 将json中的问题转为数组 const newQuestions = Object.keys(questions.content).map(key => questions.content[key].question) const initialState = { qID: 0, questionTxt: newQuestions[0], } const [currentQuestion, setCurrentQuestion] = useState(0) const [questionCtx, setQuestionCtx] = useState(initialState) const updateQuestion = () => { // 修正边界判断,防止越界 if(currentQuestion >= newQuestions.length - 1) { console.log("no more questions") return } // 函数式更新获取最新状态,避免闭包问题 setCurrentQuestion(prev => prev + 1) setQuestionCtx(prev => ({ qID: prev.qID + 1, questionTxt: newQuestions[prev.qID + 1] })) } // 传递响应式状态questionCtx return ( <QuestionContext.Provider value={{ questionCtx, updateQuestion }}> {props.children} </QuestionContext.Provider> ) } export default SectionState
同步修改Questions.js
因为上下文字段从newState改为questionCtx,需要对应调整:
import { React, useContext } from 'react' import './styles/Questions.css' import QuestionContext from '../context/QuestionContext' const Questions = () => { const newContext = useContext(QuestionContext) return ( <> <h1 className='text-4xl text-zinc-50'>{ newContext.questionCtx.questionTxt }</h1> </> ) } export default Questions
内容的提问来源于stack exchange,提问作者dartHTh0t
相关产品推荐
相关产品推荐

