You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中使用fabric.js如何通过onClick事件正常添加canvas对象

问题原因
  • 你把fabric画布初始化逻辑写在组件函数顶层,React函数组件每次重渲染都会重新执行函数体,这会反复创建全新的fabric画布实例,这些新实例并没有正确绑定到页面上实际渲染的canvas DOM节点。点击事件触发时,你操作的是脱离真实DOM的无效实例,添加的矩形自然不会显示在页面上。
  • fabric画布初始化必须等对应的canvas DOM元素挂载到页面后再执行,直接在函数顶层执行初始化时机不对,大概率会拿到还没完成渲染的DOM,导致初始化异常。
修复方案

用useRef存储fabric画布实例,在DOM挂载完成的useEffect钩子里只做一次画布初始化,后续点击事件直接操作ref中保存的有效实例即可,修复后的完整代码如下:

import { useEffect, useRef } from 'react';
import { fabric } from 'fabric';

const Canvasbody = () => {
  const canvasRef = useRef(null);

  useEffect(() => {
    // DOM挂载完成后初始化画布,仅执行一次
    canvasRef.current = new fabric.Canvas('canvas-main');

    // 组件卸载时销毁实例,避免内存泄漏
    return () => {
      canvasRef.current?.dispose();
      canvasRef.current = null;
    }
  }, []);

  const handleAddRect = () => {
    if (!canvasRef.current) return;
    const rect = new fabric.Rect({
      height: 280,
      width: 200,
      fill: 'yellow',
      left: 20,
      top: 20
    });
    canvasRef.current.add(rect);
    // 若遇到添加后不刷新的情况,放开下面这行强制重绘
    // canvasRef.current.renderAll();
  }

  return (
    <>
      <canvas
        style={{ border: 'solid 1px #555' }}
        id="canvas-main"
        width="600px"
        height="600px"
      />
      <button onClick={handleAddRect}>Click me</button>
    </>
  );
};

export default Canvasbody;

注意:不要在组件函数顶层直接调用new fabric.Canvas(),否则只要组件发生重渲染就会重复创建实例,不仅会导致操作不生效,还会造成内存泄漏。

内容的提问来源于stack exchange,提问作者Sohaib Ashraf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 04:03:41