React中修改所有按钮backgroundColor时querySelector返回null如何解决
问题根因
- 选择器语法错误:
document.querySelector('data-key')是寻找标签名为<data-key>的元素,而要匹配data-key自定义属性需要用属性选择器语法[data-key="对应值"] - 用法不符合React设计规范:你直接操作DOM修改样式,而按钮颜色是绑定在
NumbersParent组件内部的numbersColor状态上的,组件后续重渲染时会覆盖你手动修改的DOM样式;且NumbersParent定义在父组件内部,每次父组件重渲染都会重建该组件,内部状态会丢失 - 语法错误:你当前代码的return语句写在了
newBet组件函数体外部,属于语法错误,且React组件名必须首字母大写,小写开头的组件会被识别为普通HTML标签 - 自定义属性透传问题:你把
data-key写在自定义组件NumbersParent上,如果没有手动把该属性透传到内部渲染的DOM元素上,真实DOM上根本不会存在data-key属性,自然也无法通过选择器匹配到
正确实现方案
推荐使用React状态驱动的方式实现,不要操作原生DOM:将按钮颜色状态提升到父组件统一管理,clearGame时直接修改父组件状态即可全局生效。
// React组件名必须首字母大写 const NewBet: React.FC = () => { // 父组件维护所有数字按钮的选中状态 const [selectedNumbers, setSelectedNumbers] = useState<Set<number>>(new Set()) const clearGame = () => { // 直接清空选中集合,所有按钮颜色自动恢复默认 setSelectedNumbers(new Set()) }; const NumbersParent = (props: { num: number, children: React.ReactNode }) => { const isSelected = selectedNumbers.has(props.num) const currentColor = isSelected ? gamesJson[whichLoteriaIsVar].color : '#ADC0C4' const changeButtonColor = () => { setSelectedNumbers(prev => { const newSet = new Set(prev) isSelected ? newSet.delete(props.num) : newSet.add(props.num) return newSet }) }; return ( <Numbers color={currentColor} onClick={changeButtonColor} > {props.children} </Numbers> ); }; return ( <> <NumbersContainer> {numbersList.map((num) => ( <NumbersParent key={num} num={num}> {num} </NumbersParent> ))} </NumbersContainer> <Button onClick={clearGame}>Clear Game</Button> </> ) }
如果非要用原生DOM的方式(非常不推荐,后续容易出现状态和DOM不一致的问题),可以修改选择器逻辑,同时确保data-key属性已经透传到真实DOM:
const clearGame = () => { // 直接选中所有带data-key属性的元素批量修改 document.querySelectorAll<HTMLElement>('[data-key]').forEach(el => { el.style.backgroundColor = '#ADC0C4' }) };
内容的提问来源于stack exchange,提问作者Guilherme
相关产品推荐
相关产品推荐

