recherche

Maison  >  Questions et réponses  >  le corps du texte

Re-rendu à l'aide de React.StrictMode et de l'instance Canvas de fabric.js

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粉659378577P粉659378577431 Il y a quelques jours854

répondre à tous(1)je répondrai

  • P粉850680329

    P粉8506803292023-09-22 18:33:02

    Question

    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.

    Solution

    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>

    répondre
    0
  • Annulerrépondre