The HTML5 `<canvas>` element provides an API for drawing graphics using JavaScript. While React is a declarative library for building user interfaces, the Canvas API is inherently imperative (you tell it *how* to draw each pixel). Integrating them involves bridging this gap by using React's lifecycle hooks and refs to access the underlying DOM element and then manipulate the canvas imperatively.
How it Works:
1. Canvas Element: You render a standard `<canvas>` HTML element within your React component.
2. Refs: To interact with the canvas element directly (which is necessary for calling its drawing methods), you use React's `useRef` hook. This hook allows you to create a mutable ref object whose `.current` property will hold the DOM node once the component mounts.
3. Drawing Logic with `useEffect`: The core drawing logic is placed inside a `useEffect` hook. This ensures that the drawing operations occur *after* the DOM element has been rendered and is available. The `useEffect` hook is ideal because:
* It runs after every render, or when its dependencies change, allowing you to redraw the canvas if props or state affecting the drawing change.
* It can optionally return a cleanup function, which can be useful for stopping animations or releasing resources if the component unmounts.
4. 2D Rendering Context: Inside `useEffect`, you first obtain the 2D rendering context from the canvas element using `canvas.getContext('2d')`. This context object exposes all the drawing methods (e.g., `fillRect`, `strokeRect`, `lineTo`, `arc`, `fillText`, `clearRect`).
5. Imperative Drawing: With the context, you then use the imperative Canvas API methods to draw shapes, lines, text, images, etc.
Key Considerations:
* Performance: For complex animations or highly dynamic graphics, consider using `requestAnimationFrame` within your `useEffect` to ensure smooth rendering and efficient resource usage. Also, be mindful of re-drawing the entire canvas unnecessarily.
* State Management: If your canvas drawing depends on component state or props, ensure they are listed in the `useEffect`'s dependency array so that the canvas updates when these values change.
* Libraries: For more advanced graphics or easier declarative drawing on canvas, consider third-party libraries like `react-konva` (for Konva.js) or `react-p5` (for P5.js), which wrap these imperative APIs into more React-friendly components.
Example Code
import React, { useRef, useEffect } from 'react';
interface CanvasProps {
width: number;
height: number;
backgroundColor?: string;
drawColor?: string;
}
const MyCanvas: React.FC<CanvasProps> = ({ width, height, backgroundColor = '#f0f0f0', drawColor = 'blue' }) => {
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext('2d');
if (!ctx) return;
// Clear the canvas before drawing (important for re-renders)
ctx.clearRect(0, 0, width, height);
// Set background color
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, width, height);
// Draw a simple blue rectangle
ctx.fillStyle = drawColor;
ctx.fillRect(50, 50, 100, 75);
// Draw a red circle
ctx.beginPath();
ctx.arc(200, 100, 40, 0, Math.PI * 2, true); // x, y, radius, startAngle, endAngle, anticlockwise
ctx.fillStyle = 'red';
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = 'black';
ctx.stroke();
// Draw some text
ctx.font = '24px Arial';
ctx.fillStyle = 'green';
ctx.fillText('Hello Canvas!', 60, 180);
}, [width, height, backgroundColor, drawColor]); // Re-draw if these props change
return (
<div>
<canvas
ref={canvasRef}
width={width}
height={height}
style={{ border: '1px solid #ccc', display: 'block', margin: '20px auto' }}
>
Your browser does not support the HTML canvas tag.
</canvas>
<p style={{ textAlign: 'center', fontSize: '0.8em', color: '#666' }}>
Drawing a {drawColor} rectangle, a red circle, and some text.
</p>
</div>
);
};
export default MyCanvas;
// To use this component in your App.tsx or another component:
// import MyCanvas from './MyCanvas';
// function App() {
// return (
// <div className="App">
// <h1>React Canvas Example</h1>
// <MyCanvas width={300} height={200} drawColor="purple" />
// <MyCanvas width={400} height={250} backgroundColor="lightblue" drawColor="darkgreen" />
// </div>
// );
// }
// export default App;








Canvas and Graphics with React