React中基于data属性切换面板报错:Cannot read properties of undefined
问题修复方案
错误原因分析
this指向异常:React中直接传递普通函数作为点击回调时,函数内部的this默认是undefined(严格模式下),导致无法通过this.getAttribute()获取元素属性。- 全局DOM操作不符合React设计思路:直接用
document.querySelector操作DOM会绕过React的状态管理,容易引发UI与状态不一致的问题。 - 拼写错误:选择器
nagivation__li应为navigation__li。 - 语法错误:
this.addClass("selected")是jQuery语法,原生JS需用this.classList.add("selected")。 - Screen组件默认全部添加
active类,不符合仅初始激活screenOne的需求。
修复后的代码实现
1. src/pages/Homepage(状态提升,统一管理激活面板)
import React from "react"; import Screen from "../components/Screen/Screen"; import Navigation from "../components/Navigation/Navigation"; class Homepage extends React.Component { constructor(props) { super(props); // 初始化状态,默认激活screenOne this.state = { activePanel: "screenOne" }; // 绑定this,确保回调中this指向组件实例 this.handlePanelChange = this.handlePanelChange.bind(this); } handlePanelChange(panelID) { // 更新激活面板状态 this.setState({ activePanel: panelID }); } render(){ const { activePanel } = this.state; return ( <section id="project"> <Screen id="screenOne" tag="Panel 1" header="Screen 1" isActive={activePanel === "screenOne"} /> <Screen id="screenTwo" tag="Panel 2" header="Screen 2" isActive={activePanel === "screenTwo"} /> <Navigation activePanel={activePanel} onPanelChange={this.handlePanelChange} /> </section> ); } } export default Homepage;
2. src/components/Navigation(接收状态与回调,控制选中项)
import React from 'react'; import { Container, Row, Col } from 'react-bootstrap'; class Navigation extends React.Component{ render(){ const { activePanel, onPanelChange } = this.props; return( <div className="navigation"> <Container> <Row> <Col> <nav className="navigation__nav"> <Container> <Row className="justify-content-center"> <Col> <ul className="navigation__ul reset-list d-flex justify-content-between"> <li className={`navigation__li ${activePanel === "screenOne" ? "selected" : ""}`} onClick={() => onPanelChange("screenOne")} > Panel 1 </li> <li className={`navigation__li ${activePanel === "screenTwo" ? "selected" : ""}`} onClick={() => onPanelChange("screenTwo")} > Panel 2 </li> </ul> </Col> </Row> </Container> </nav> </Col> </Row> </Container> </div> ) } } export default Navigation;
3. src/components/Screen(根据props判断是否激活)
import React from 'react'; import { Container, Row, Col } from 'react-bootstrap'; function Screen(props) { const { id, tag, header, isActive } = props; return( <div className={`panel ${isActive ? "active" : ""}`} id={id}> <Container> <Row className="justify-content-center align-items-center"> <Col xs={12} md={6}> <div className="panel__left fadeIn"> <h1 className="panel__left-title"> <span className="d-block">{tag}</span> <span className="d-block">{header}</span> </h1> </div> </Col> </Row> </Container> </div> ) } export default Screen;
4. 移除src/utils/helpers(逻辑已整合到父组件,无需单独维护)
核心优化点
- 状态提升:将激活面板的状态放在父组件Homepage中,统一管理Navigation和Screen的状态,符合React单向数据流原则。
- 避免DOM操作:通过props传递状态和回调,由React负责UI渲染,消除直接操作DOM带来的潜在问题。
- 修复this指向:通过绑定父组件方法或使用箭头函数,确保回调中的this指向正确。
- 修正语法错误:修复拼写错误和原生JS语法问题。
内容的提问来源于stack exchange,提问作者Freddy
相关产品推荐
相关产品推荐

