我正在創建一個織物畫布和按鈕,這些按鈕實例化的形狀應該是可選擇的。我不明白為什麼在以下情況下我的元件會被重新渲染兩次。因此,我的織物形狀無法選擇。然而,當我從我的index.tsx檔案中移除
時,渲染只發生一次,我的形狀是可選擇的。我可以移除
,但我不認為這是最好的解決方案。下面是示範:
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>
P粉8506803292023-09-22 18:33:02
為什麼 useEffect 在 React 中運行兩次,如何處理? 這個問題有很好的答案,描述了為什麼會發生這種情況以及一個通用的解決方案。
在你的情況下,你需要清理實例化的畫布。我對 Fabric 不熟悉,但從閱讀文件中,dispose
方法 似乎是合適的:
你需要從 useEffect
傳回一個呼叫上述方法的函數。從連結的問題可以看出,從 useEffect
傳回一個進行清理的函數是一個好的實踐。下面也有一個工作範例:
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(); return () => canvasRef.current.dispose(); }, []); 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>; } const strictModeEnabledRoot = createRoot(document.getElementById("strict-mode-enabled")); strictModeEnabledRoot.render(<StrictModeEnabled />);
<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>