React map遍历渲染组件时如何仅禁用当前被点击的按钮
问题根因
你现在用全局单个布尔状态disable控制所有题目的按钮禁用状态,所有题目组件都共享这一个值。只要点任意一个正确答案按钮把这个状态改成true,所有绑定了这个状态的按钮都会一起禁用,自然会出现点一题锁所有题的情况。
修复方案
不要用全局布尔值统一控制,把禁用标记放到每道题自己的数据里,点击的时候只改当前题的禁用标记就行,改完之后每个按钮的状态互不影响。具体改法:
- 删掉父组件里全局的
disable状态声明 - 接口拿到题目数据之后,给每道题加个
isDisabled字段,初始值设为false - 修改得分函数,接收当前点击题目的索引,更新状态的时候只把对应索引题目的
isDisabled改成true - 遍历渲染题目的时候,把当前题的索引、自己的禁用状态、绑了索引参数的点击回调传给子组件
修改后的完整代码
const [request, setRequest] = React.useState([]) const [score, setScore] = React.useState(0); function scoreFunction (index){ // 仅更新当前点击题目的禁用状态 setRequest(prev => prev.map((item, i) => { return i === index ? {...item, isDisabled: true} : item })) setScore(prevScore => prevScore + 1) } React.useEffect (() => { fetch('https://opentdb.com/api.php?amount=5') .then(res => res.json()) .then(data => setRequest(data.results.map(({ question, correct_answer, incorrect_answers }) => ({ question, correct_answer, incorrect_answers, isDisabled: false // 每个题目独立维护禁用状态 })))) }, []) const questionElements = request.map((req, index) => { return ( <Question key={index} question = {req.question} correct_answer ={req.correct_answer} incorrect_answers = {req.incorrect_answers} scoreFunction = {() => scoreFunction(index)} disabled = {req.isDisabled} /> ) }) // Question 子组件 export default function Question (props){ const incorrectAnswers = props.incorrect_answers.map((ans, idx) => { // 如果需要错误答案点击后也禁用,参照正确答案的逻辑补充状态和事件即可 return ( <button key={idx} className ="button">{ans}</button> ) }) return( <div className = "question-div"> <h1 className = "question">{props.question}</h1> <div className = "answerBlock"> <button disabled = {props.disabled} className ="button correct" onClick = {props.scoreFunction}>{props.correct_answer} </button> {incorrectAnswers} </div> <hr /> </div> ) }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
内容的提问来源于stack exchange,提问作者Abdullahi Olateju
相关产品推荐
相关产品推荐

