Ich erstelle eine Stoffleinwand und Knöpfe. Die durch diese Knöpfe instanziierten Formen sollten auswählbar sein. Ich verstehe nicht, warum meine Komponente in der folgenden Situation zweimal neu gerendert wird. Daher kann meine Stoffform nicht ausgewählt werden. Wenn ich jedoch
时,渲染只发生一次,我的形状是可选择的。我可以移除
aus meiner index.tsx-Datei entferne, halte ich das nicht für die beste Lösung. Hier ist die Demo:
const { Fragment, StrictMode, useEffect, useRef } = React; const { createRoot } = ReactDOM; const styles = {}; const CanvasComponent = ({ id }) => { const canvasRef = useRef(null); useEffect(() => { console.log('init canvas'); // displayed twice with <React.StrictMode> canvasRef.current = initCanvas(); }, []); const initCanvas = () => ( canvasRef.current = new fabric.Canvas(`canvas-${id}`, { width: 800, height: 400, }) ); const addShape = (shapeType: string) => { let shape: fabric.Object; switch (shapeType) { case 'circle': shape = new fabric.Circle({ radius: 30, fill: 'red', left: 100, top: 100 }); break; case 'rectangle': shape = new fabric.Rect({ width: 60, height: 70, fill: 'green', left: 100, top: 100 }); break; default: return; } canvasRef.current.add(shape); }; return ( <div> <button onClick={() => addShape('circle')}>Add Circle</button> <button onClick={() => addShape('rectangle')}>Add Rectangle</button> <div className={styles.canvasContainer}> <canvas id={`canvas-${id}`}></canvas> </div> </div> ); } function StrictModeEnabled() { return <StrictMode><h1>Strict Mode Enabled</h1><CanvasComponent id={1} /></StrictMode>; } function StrictModeDisabled() { return <Fragment><h1>Strict Mode Disabled</h1><CanvasComponent id={2} /></Fragment>; } const strictModeEnabledRoot = createRoot(document.getElementById("strict-mode-enabled")); strictModeEnabledRoot.render(<StrictModeEnabled />); const strictModeDisabledRoot = createRoot(document.getElementById("strict-mode-disabled")); strictModeDisabledRoot.render(<StrictModeDisabled />);
<script crossorigin src="https://www.unpkg.com/fabric@5.3.0/dist/fabric.js"></script> <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script> <div id="strict-mode-enabled"></div> <div id="strict-mode-disabled"></div>
问题
为什么 useEffect 在 React 中运行两次,如何处理? 这个问题有很好的答案,描述了为什么会发生这种情况以及一个通用的解决方案。
解决方案
在你的情况下,你需要清理实例化的画布。我对 Fabric 不熟悉,但从阅读文档中,
dispose
方法 似乎是合适的:你需要从
useEffect
返回一个调用上述方法的函数。从链接的问题中可以看出,从useEffect
返回一个进行清理的函数是一个好的实践。下面也有一个工作示例: