Maison > Questions et réponses > le corps du texte
Je crée une toile en tissu et des boutons, les formes instanciées par ces boutons doivent être sélectionnables. Je ne comprends pas pourquoi mon composant est restitué deux fois dans la situation suivante. Par conséquent, la forme de mon tissu ne peut pas être sélectionnée. Cependant, lorsque je supprime
时,渲染只发生一次,我的形状是可选择的。我可以移除
de mon fichier index.tsx, je ne pense pas que ce soit la meilleure solution. Voici la démo :
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
Pourquoi useEffect s'exécute deux fois dans React et comment y faire face ? Cette question a une bonne réponse décrivant pourquoi cela se produit et une solution générale.
Dans votre cas, vous devez nettoyer le canevas instancié. Je ne connais pas Fabric, mais à la lecture de la documentation, la dispose
méthode semble appropriée :
C'est une bonne pratique que vous deviez renvoyer une fonction de useEffect
返回一个调用上述方法的函数。从链接的问题中可以看出,从 useEffect
qui effectue le nettoyage. Vous trouverez également un exemple fonctionnel ci-dessous :
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>