React Bootstrap ToggleButtonGroup添加图片及按钮点击失效解决方法
问题根源
react-bootstrap 的 ToggleButtonGroup 组件要求直接子元素必须是 ToggleButton,你在外层包裹了 div 之后,ToggleButton 不再是 ToggleButtonGroup 的直接子节点,组件内置的单选状态同步、事件绑定逻辑全部失效,所以点击无响应。
解决方案
- 用 React 空标签(
<> </>,即 React.Fragment)替代外层 div,它不会生成真实的 DOM 节点,既满足你返回两个同级元素的语法要求,又能让ToggleButton成为ToggleButtonGroup的直接子元素,保证组件逻辑正常运行。 - 修正原有逻辑缺陷:你把
setFinishedGameHandler调用放在了determineButtonVariant方法里,这个方法在每次组件渲染时都会遍历所有选项执行,属于渲染过程中的非法副作用,应该把答案正确性判断逻辑挪到选择答案的handleAnswerChange回调中执行。 - 补充 map 遍历的 key 属性,避免 React 渲染警告。
修改后完整代码如下:
import { useState } from 'react'; import { ToggleButtonGroup, ToggleButton } from 'react-bootstrap'; import './css/GameAnswers.css'; import GameImage from './GameImage'; type GameAnswersProps = { arrayAnswers: Array<string>, arrayAnswersImages?: Array<string>, correctAnswer: string, setFinishedGameHandler: (isSuccess: boolean) => void } function GameAnswers(props: GameAnswersProps) { const [selectedAnswer, setSelectedAnswer] = useState(""); const handleAnswerChange = function (e: React.ChangeEvent<HTMLInputElement>) { const currentValue = e.target.value; setSelectedAnswer(currentValue); // 答案判断逻辑移到这里,只有选择答案时才执行 props.setFinishedGameHandler(currentValue === props.correctAnswer); } const determineButtonVariant = function (answer: string) { if (answer !== selectedAnswer) { return "primary"; } return answer === props.correctAnswer ? "success" : "danger"; } return ( <div className="game-answers"> { !props.arrayAnswersImages && <GameImage className="game-details-image" images={[{ imgSrc: "/Untitled.png", imgAlt: 'test' }]} /> } <ToggleButtonGroup type="radio" name="answers"> {props.arrayAnswers.map(function (answer, index) { // 用空标签替代div,不生成额外DOM节点 return <React.Fragment key={answer}> {props.arrayAnswersImages && <GameImage className="game-togglebutton" images={[{ imgSrc: props.arrayAnswersImages[index], imgAlt: 'test' }]} /> } <ToggleButton id={answer} value={answer} onChange={handleAnswerChange} variant={determineButtonVariant(answer)} >{answer}</ToggleButton> </React.Fragment> })} </ToggleButtonGroup> </div> ); } export default GameAnswers;
内容的提问来源于stack exchange,提问作者Octavian Niculescu
相关产品推荐
相关产品推荐

