React中通过setter修改div样式导致组件内容丢失问题排查
问题分析与修复方案
核心问题
你的代码存在三个关键错误,导致点击按钮后组件内容异常:
组件定义与Hooks使用违规
DraggableElement定义在AppWindow内部,每次width状态更新时,这个组件会被重新创建,导致其内部的Draggable钩子重复执行,破坏拖拽逻辑的状态,进而引发元素渲染异常。同时,直接在组件函数内部调用Draggable(dragRef, dragRefParent)不符合React Hooks使用规范(Hooks必须以use开头且在组件顶层调用),会导致refs和拖拽逻辑的状态管理混乱。子组件参数接收错误
MaximizeButton组件的参数接收方式错误,你直接把props对象当成了givenWidth值。点击按钮时,实际传入setWidth的是一个对象而非数值,导致width状态变成对象,style={{width: width}}失效,容器宽度异常,内容看起来"丢失"。全屏实现逻辑缺陷
当前仅设置宽度为固定值(600),没有实现真正的全屏(占满屏幕宽高),且缺少明确的单位处理(虽然React对数字会自动加px,但明确写出更清晰,便于适配百分比/vw等场景)。
修复后的代码
import { useRef, useState, useEffect } from "react"; import Draggable from "./hooks/draggable"; // 将DraggableElement移到外部,避免每次渲染重新创建组件 const DraggableElement = ({ dragElement, parentElement, width }) => { const dragRef = useRef(null); const dragRefParent = useRef(null); // 用useEffect包裹Draggable调用,确保仅在refs就绪时执行,同时支持清理 useEffect(() => { if (dragRef.current && dragRefParent.current) { const cleanup = Draggable(dragRef, dragRefParent); return cleanup; } }, [dragRef, dragRefParent]); return ( <div ref={dragRefParent} className="draggable-parent dialog" style={{ width: `${width}px`, height: width === window.innerWidth ? '100vh' : 'auto' }} > <div ref={dragRef} className="draggable-child"> {dragElement} </div> {parentElement} </div> ); }; // 正确解构props参数 const MaximizeButton = ({ givenWidth, onClick }) => { return ( <button onClick={() => onClick(givenWidth)}>MAXIMIZE</button> ); }; export function AppWindow() { const [width, setWidth] = useState(400); // 实现全屏/还原的切换逻辑 const handleMaximize = () => { setWidth(prev => prev === window.innerWidth ? 400 : window.innerWidth); }; return ( <DraggableElement width={width} dragElement={ <div className="app-title"> Application Title goes here <div className="app-topbar"> <button onClick={handleMaximize}>Maximize</button> <MaximizeButton givenWidth={window.innerWidth} onClick={setWidth} /> </div> </div> } parentElement={ <div> <div className="contents"> Contents of the application here </div> </div> } /> ); }
关键修复说明
- 组件拆分:将
DraggableElement移到AppWindow外部,避免状态更新时组件重复创建,保留拖拽逻辑的状态。 - Hooks规范:用
useEffect包裹Draggable调用,确保仅在refs就绪时执行,同时支持清理函数避免内存泄漏。 - 参数修正:
MaximizeButton正确解构props,确保传入的是数值而非对象。 - 全屏逻辑优化:新增切换逻辑,点击按钮在默认宽度和屏幕宽度之间切换,同时设置高度为
100vh实现全屏,非全屏时高度自动适配内容。
内容的提问来源于stack exchange,提问作者JSJB
相关产品推荐
相关产品推荐

