React组件中querySelector传入this触发报错该如何解决
错误原因&修复方案
直接报错原因
document.querySelector() 方法要求传入的参数是字符串格式的CSS选择器,你传入的this是当前触发点击事件的<li> DOM元素对象,不是合法的选择器字符串,所以直接抛出你遇到的语法错误。
其他隐含问题
- 你通过
document.querySelector('#client-list > li')绑定事件,只会匹配到第一个<li>元素,第二个列表项点击不会触发任何逻辑 - 代码中混用了jQuery方法和原生DOM API:
removeClass()、index()都是jQuery实例的方法,原生DOM元素没有这两个方法,就算解决了当前报错,后续也会继续报错 - 在React中手动绑定DOM事件容易出现内存泄漏风险,你当前的useEffect没有返回清除事件监听的清理函数
修复方案
方案1:修正现有原生JS写法的问题
useEffect(() => { // 给所有li绑定事件 const listItems = document.querySelectorAll('#client-list > li'); const handleClick = function (e) { e.preventDefault(); // this就是当前点击的li元素,不需要再querySelector获取 // 计算当前li的下标 const currentIndex = Array.from(listItems).findIndex(item => item === this); const clientParent = document.querySelector('.client-parent'); if (currentIndex === 0) { // 用原生classList操作类名 clientParent.classList.remove('hidden'); document.querySelector('.client-avatar-output').classList.add('mb-2'); } else { clientParent.classList.add('hidden'); } } listItems.forEach(item => item.addEventListener('click', handleClick)); // 返回清理函数,避免内存泄漏 return () => { listItems.forEach(item => item.removeEventListener('click', handleClick)); } }, []); return ( <ul id='client-list'> <li>Item1</li> <li>Item2</li> </ul> )
方案2:更符合React设计理念的写法(推荐)
不需要手动操作DOM绑定事件,直接用React合成事件实现逻辑:
const ClientList = () => { const handleItemClick = (index) => { const clientParent = document.querySelector('.client-parent'); if (index === 0) { clientParent.classList.remove('hidden'); document.querySelector('.client-avatar-output').classList.add('mb-2'); } else { clientParent.classList.add('hidden'); } } return ( <ul id='client-list'> <li onClick={() => handleItemClick(0)}>Item1</li> <li onClick={() => handleItemClick(1)}>Item2</li> </ul> ) }
如果类名控制的元素也是当前组件渲染的,还可以进一步用state来控制类名切换,完全不用操作DOM,更符合React的声明式写法。
内容的提问来源于stack exchange,提问作者Mani
相关产品推荐
相关产品推荐

