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

React中Canvas页面刷新无显示,热重载正常的技术求助

React Canvas刷新后不显示,热重载正常的问题修复

问题场景

React项目中开发Canvas功能时遇到异常:页面刷新后Canvas无法显示内容,但修改代码触发热重载时,Canvas能正常渲染输出。

问题原因

你的代码存在两个核心问题:

  • 初始screenWidth设为1,组件挂载时的空依赖useEffect执行时,Canvas实际宽度为1,此时绘制的路径被压缩到1px画布上完全不可见。之后调用windowResizeOnLoad更新screenWidth为窗口宽度,Canvas因属性变化重新渲染,但挂载阶段的useEffect已执行完毕,不会重新绘制路径。
  • 热重载时React会保留组件状态,screenWidth已为正确的窗口宽度,所以挂载时的绘制能在正常尺寸的Canvas上显示。

修复方案

将绘制逻辑与Canvas尺寸状态关联,确保尺寸更新时重新绘制,同时清理resize事件监听避免内存泄漏:

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

function CanvasComponent() {
  const [screenWidth, setScreenWidth] = useState(window.innerWidth - 2);
  const [screenHeight, setScreenHeight] = useState(2527);
  const canvasRef = useRef(null);

  // 提取绘制逻辑为独立函数
  const drawCanvas = () => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    
    // 清空画布,避免多次绘制叠加
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    
    ctx.beginPath();
    ctx.strokeStyle = '#D4AF38';
    ctx.moveTo(100, 10);
    ctx.bezierCurveTo(100, 90, 1100, 320, 100, 600);
    ctx.stroke(); 
  };

  // 监听窗口resize事件,更新画布宽度
  useEffect(() => {
    const handleResize = () => {
      setScreenWidth(window.innerWidth - 2);
    };
    window.addEventListener('resize', handleResize);
    // 组件卸载时移除监听,防止内存泄漏
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  // 画布尺寸变化时重新绘制内容
  useEffect(() => {
    drawCanvas();
  }, [screenWidth, screenHeight]);

  return (
    <canvas width={screenWidth} height={screenHeight} ref={canvasRef}></canvas>
  );
}

export default CanvasComponent;

关键改动说明

  • 初始screenWidth直接设为window.innerWidth - 2,避免初始画布尺寸异常
  • 提取drawCanvas函数,复用绘制逻辑
  • 新增依赖screenWidth和screenHeight的useEffect,确保尺寸变化时自动重新绘制
  • 清理resize事件监听,避免内存泄漏
  • 绘制前清空画布,防止多次绘制叠加

内容的提问来源于stack exchange,提问作者Salman Khan Sohoo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 08:35:24