// Film.tsx 当前代码(有问题)
const generateCell = (imageId, indexOfCell) => {
return (<ViewportContainer imageId={imageId} currentFilm={currentFilm} indexOfCell={indexOfCell} />);
};
<ViewportContainer imageId="image-A" .../><ViewportContainer imageId="image-B" .../>// ViewportContainer 内部状态在组件重用时不会重置
const [hasImage, setHasImage] = useState<boolean>(false);
const [currentImageId, setCurrentImageId] = useState<string | null>(null);
const [stackViewport, setStackViewport] = useState<any>(null);
const viewportRef = useRef(null);
// 🚨 问题:切换胶片时这些状态保持原值!
// useEffect 只在组件首次挂载时执行
useEffect(() => {
// 创建渲染引擎和 viewport...
setStackViewport(viewport);
}, []); // 空依赖数组意味着只执行一次
// 🚨 关键问题:viewport 实例仍然绑定着之前的图像数据
imageId 改变,viewport 可能仍显示缓存的图像useEffect([imageId, stackViewport]) 虽然会触发,但 stackViewport 实例本身没变1. 用户在胶片1拖拽图像A到第一个格子
- ViewportContainer 创建 viewport-1
- viewport-1 显示图像A
- hasImage = true, currentImageId = "imageA"
2. 用户切换到胶片2(第一个格子为空)
- React 重用 ViewportContainer 组件实例
- props 更新:imageId 从 "imageA" 变为 null
- 但是 viewport-1 实例仍然存在,仍然显示图像A
- 虽然触发 useEffect,但清空逻辑可能执行不彻底
3. 结果:胶片2显示了胶片1的图像
// 修复后的代码
const generateCell = (imageId, indexOfCell) => {
const uniqueKey = `${currentFilm.id}-${indexOfCell}`;
return (
<ViewportContainer
key={uniqueKey} // 🎯 关键修复
imageId={imageId}
currentFilm={currentFilm}
indexOfCell={indexOfCell}
/>
);
};
1. 切换胶片时,key 从 "1-0" 变为 "2-0"
2. React 识别这是不同的组件,卸载旧组件,创建新组件
3. 旧组件卸载 → 触发 cleanup 函数 → 清理 viewport
4. 新组件挂载 → 重新初始化所有状态 → 创建新的 viewport
5. 结果:完全隔离,没有状态残留
核心问题:React 组件重用 + Cornerstone Viewport 状态持久化 根本原因:没有 key 导致 React 错误地重用了应该重新创建的组件 解决方案:通过 key 强制 React 在胶片切换时重新创建组件实例