React中跨组件点击按钮控制display:none元素显示的问题
React点击按钮显示指定元素的正确实现
问题背景
需求:点击按钮后在页面上显示指定窗口元素。
遇到的问题:尝试通过document.getElementById("window")获取元素存入变量,但变量值为null,仅第一次运行偶然有效。
疑问:是否需要使用props?该怎么用?或者变量应该放在哪里?
原代码示例
import "./App.css"; const window = document.getElementById("window"); console.log(window); window.style.display = "none"; function Window() { return ( <> <div id="window"></div> </> ); } function Div() { return ( <> <div className="divStyle"> <button id="button" onClick={function () { window.style.display = "block"; }} > DETAILS </button> </div> </> ); } function App() { return ( <> <h1>Products</h1> <div id="main"> <Div /> <Window /> </div> </> ); } export default App;
问题原因
你当前的写法犯了两个React中的典型错误:
- DOM获取时机不对:在组件渲染之前就调用
document.getElementById,此时<Window />组件还没被渲染到真实DOM里,自然拿不到元素,返回null。哪怕第一次偶然生效,后续React重新渲染时,虚拟DOM的更新也会覆盖你手动修改的样式。 - 违背React声明式原则:直接操作真实DOM不符合React的设计理念,React是通过状态来驱动UI更新的,手动修改DOM会导致虚拟DOM和真实DOM不同步,引发各种奇怪问题。
正确解决方案:用状态+props实现
不需要直接操作DOM,我们通过React的状态管理来控制元素的显示隐藏,利用props在组件间传递状态和回调:
import "./App.css"; import { useState } from 'react'; // Window组件接收show状态,控制显示 function Window({ show }) { return ( <div id="window" style={{ display: show ? 'block' : 'none' }} ></div> ); } // Div组件接收点击回调,触发显示状态修改 function Div({ onShowWindow }) { return ( <div className="divStyle"> <button id="button" onClick={() => onShowWindow(true)} > DETAILS </button> </div> ); } function App() { // 在父组件App中定义控制窗口显示的状态 const [showWindow, setShowWindow] = useState(false); return ( <> <h1>Products</h1> <div id="main"> {/* 将修改状态的方法传给Div组件 */} <Div onShowWindow={setShowWindow} /> {/* 将显示状态传给Window组件 */} <Window show={showWindow} /> </div> </> ); } export default App;
关键说明
- 状态提升:因为
Div和Window是兄弟组件,无法直接通信,所以把控制显示的状态放在它们的父组件App中,通过props传递给子组件。 - 声明式渲染:你只需要告诉React“当showWindow为true时显示元素,否则隐藏”,React会自动处理DOM的更新,不需要手动操作。
- props的作用:在这里props用来传递两个关键内容:给
Div传递修改状态的回调函数,给Window传递当前的显示状态,实现组件间的协作。
内容的提问来源于stack exchange,提问作者Zoltán Fodor
相关产品推荐
相关产品推荐

