# react-sketch-canvas: freehand drawing on an SVG canvas in React

> This component draws with SVG rather than with a bitmap canvas, which means the sketch you produce is vector data from the start, and the readme is unusually complete about the props, the events and the export path.

**vinothpandian/react-sketch-canvas** — Freehand vector drawing component for React using SVG as canvas 🖌️

- Repository: https://github.com/vinothpandian/react-sketch-canvas
- Website: https://vinoth.info/react-sketch-canvas
- Stars: 568 · Forks: 92
- Language: TypeScript
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/vinothpandian-react-sketch-canvas

## SVG as the drawing surface, not a bitmap canvas

react-sketch-canvas is a freehand vector drawing component for React that uses SVG as its canvas, and that single design choice explains most of what the library does and does not do.

A bitmap canvas draws into a grid of pixels. An SVG canvas draws paths, and a path is a list of coordinates, which means the result scales to any size without blur, can be styled with CSS, and can be exported without a rasterisation step. The cost is that the browser is doing more work per stroke, and that the data you get out is a set of path elements rather than a bitmap.

The audience is a React developer who needs a drawing surface inside an application rather than a full drawing program. The features list says it supports desktop and mobile, and that it accepts input from mouse, touch and graphic tablets, and the props table includes an option to restrict the pointer type to all, mouse, pen or touch, which is the knob you turn when a stylus and a finger are used on the same device and the pen should win.

There is a live demo linked from the readme, hosted on the author's site, and the component is published to npm as react-sketch-canvas. The primary language is TypeScript, the licence is MIT, and the last push to the default branch was on 2026-10-01.

## Installing it, and the React 18 requirement

Installation is a single package manager command, and there are two documented routes.

```bash
npm i react-sketch-canvas
```

or with pnpm.

```bash
pnpm add react-sketch-canvas
```

The one hard requirement is stated in red in the readme: React 18.0.0 or newer. That is worth noticing because it is not a peer dependency range the component negotiates with, it is a floor stated up front, and an application on React 17 has to upgrade before it can use this.

The usage example is small enough to take in one look, and it shows the shape of the component: a canvas element with a style object, a width and a height, a stroke width and a stroke colour.

```javascript
import * as React from "react";
import { ReactSketchCanvas } from "react-sketch-canvas";

const styles = {
  border: "0.0625rem solid #9c9c9c",
  borderRadius: "0.25rem",
};

const Canvas = () => {
  return <ReactSketchCanvas style={styles} width="600" height="400" strokeWidth={4} strokeColor="red" />;
};
```

The width and height props are strings and default to 100%, and the documentation explains that you can specify them in em or rem, and that the canvas fills the parent element's space if they are not set. So the default behaviour is responsive, and the numeric values in the example are an explicit size.

## The props that decide how it behaves in your form

The props table is long, and most of it is obvious once you see it, so it is worth picking out the entries that change behaviour rather than appearance.

The id prop defaults to react-sketch-canvas and exists so that multiple canvases can live on one page, which matters the moment you put a signature pad inside a modal that also contains one. className and style and svgStyle handle the styling, with the last two taking CSS-in-JS objects.

The drawing controls are strokeColor, which defaults to black, canvasColor, which defaults to white and is the background of the drawing surface, strokeWidth with a default of 4, and eraserWidth with a default of 8. The background can be an image through backgroundImage, and preserveBackgroundImageAspectRatio controls how that image is scaled, with the possible values taken from the MDN documentation. The exportWithBackgroundImage flag decides what happens to that background when you export, because on false the canvas colour is set as the background instead.

Two props change behaviour in ways that are easy to miss. withTimestamp adds a timestamp to individual strokes, which the documentation describes as being for measuring sketching time, so the drawing carries timing data as well as geometry. And readOnly disables drawing on the canvas, with the important caveat that undo and redo, clear and reset still work.

That caveat is the kind of detail that decides an adoption. A read-only canvas is exactly what you want for a signature field that has already been signed, and it is not what you want if you are relying on readOnly to make a canvas inert, because the destructive actions remain available.

## Drawing state: onChange for the path, onStroke for the event

Two callbacks carry the drawing state out of the component, and they answer different questions.

onChange returns the current sketch path in the CanvasPath type on every path change. That is the whole drawing, and it is what you would save or send to a server. Since it fires on every change rather than on pointer up, it is also the hook you would use to keep a live preview or a server side save in sync.

onStroke returns the last stroke path and whether it is an eraser stroke, on every pointer up event. That is the per gesture signal, and the boolean is what lets you tell a drawing action from an erase action, which matters if you are building an undo stack by hand or recording an interaction log.

The distinction between the two is the useful part of the API design. A drawing surface has two natural granularities, the whole current state and the individual gesture, and a component that offers both avoids the situation where you have to reconstruct one from the other.

The eraser is part of the same story. The eraserWidth prop sets the erase size, and the eraser appears in the onStroke payload as a flag rather than as a separate event, so an application does not need two separate handlers to know whether the user drew or erased.

## Exporting a sketch through a ref

The methods section is short: you can export the sketch as an image or as an SVG, and you reach the element with a ref to call the functions.

The second example in the readme shows the pattern in a class component, with a createRef on the canvas and a button that calls exportImage with a format and then handles the promise.

```javascript
const Canvas = class extends React.Component {
  constructor(props) {
    super(props);

    this.canvas = React.createRef();
  }

  render() {
    return (
      <div>
        <ReactSketchCanvas ref={this.canvas} strokeWidth={5} strokeColor="black" />
        <button
          onClick={() => {
```

The export call returns a promise, which the example handles with a then that logs the data and a catch that logs the error, and the data is a data URL, so it can be dropped straight into an image tag or sent to a backend as a string.

The SVG export is the more interesting of the two for a component built on SVG, because it is the native format of what the user drew. An application that wants to keep the drawing editable, to restyle the strokes, or to compose the sketch with other vector content wants the SVG path rather than a PNG of it.

For a signature field, the image export is the practical one, and the readme links a live demo where you can try the component before installing it.

## The monorepo, changesets and the release tooling

The repository is a pnpm workspace with two packages, the component itself under packages/react-sketch-canvas and the documentation site under docs, and the root package is private with a placeholder version.

The tooling is modern and fairly opinionated. Formatting and linting are handled by Biome, with a check command over the whole tree and a format command that writes, and lefthook manages the git hooks. Coverage is tracked with codecov. The root also carries a .changeset directory, which means releases are driven by changesets rather than by editing a version field by hand, and there is a script that applies the version bump.

The scripts show how a release is actually run. The CI test target is lint, then build, then test, and the release target is the CI test, then the CI build, then the changeset version step, then changeset publish, with a separate pre-release target that stops short of the final version. There are four test commands in the component package: unit tests, a watch mode, component tests, and end to end tests.

The engine requirements are explicit as well, Node 22.13.0 or newer and pnpm 11 or newer, with pnpm 11.1.2 pinned as the package manager, and pnpm 11 is a recent enough release that the version floor is a real constraint for a team still on npm or on an older pnpm.

The release history explains the 7.0.0-next tags: the package moved through several pre-release builds of the 7.0.0 line in May 2026 before publishing 8.0.0, so a consumer pinning a next tag is opting into a line that was about to be renumbered.

## Where react-sketch-canvas is the wrong tool

Four limits, and the first is a matter of scope rather than quality.

It is a stroke renderer, not a drawing application. The props cover stroke colour, stroke width, eraser width, a background image and a read-only mode, and the events cover the current path and the last stroke. There is no shape tool, no selection, no layers, no undo stack beyond what the component provides, and no text. If you are building a diagram editor or a whiteboard with objects, this is a component for the freehand part and you will be writing the rest yourself.

The second is what the component gives you at the end. The export methods produce an image or an SVG, and the drawing you keep is whatever your onChange handler stored. The component does not define a document format, so persisting an editable sketch, undoing a change across sessions or sharing a drawing in a way another user can keep editing is your own data model to design.

The third is the pointer handling on mixed devices. The allowOnlyPointerType prop exists because touch and pen events need choosing between, and the default of all means the component does not resolve the conflict for you. On a tablet where a palm rests on the screen, you will want to think about that setting rather than leave it at the default.

The fourth is React 18. The component is written for the modern React, which is a reasonable choice for a library being maintained today, and it is a hard floor for anyone on an older application. Combined with a pnpm 11 requirement for building the repository from source, the toolchain expectations are current, which helps if your project is current and hurts if it is not.

## Conclusion

react-sketch-canvas is the right tool for a React application that needs a signature pad, a whiteboard or a sketch field where the drawing has to stay crisp at any size or be exported as an image, and it handles the mouse, touch and tablet cases in one component. It is the wrong choice for a drawing application with layers, selection handles or shapes, since the component covers strokes and the eraser and nothing else, and it is the wrong choice for a project that needs to store an editable drawing, because the exported artefact is a flattened image. Before adopting, check the readOnly prop against your requirements, because undo, redo, clear and reset still work in that mode, and confirm that the version you install is a released 8.x rather than one of the 7.0.0 pre-release builds.

## FAQ

### What is react-sketch-canvas?

It is a freehand vector drawing component for React that uses SVG as its canvas, so the strokes are vector paths rather than pixels. It supports desktop and mobile, accepts input from mouse, touch and graphic tablets, and requires React 18.0.0 or newer.

### How do I install react-sketch-canvas?

With npm i react-sketch-canvas, or with pnpm add react-sketch-canvas. The package is MIT licensed and published under that name, while the repository root is a private pnpm workspace named @vinothpandian/react-sketch-canvas that contains the component and the documentation site.

### How do I export a sketch from react-sketch-canvas?

Attach a ref to the component and call the export methods on it, for example exportImage with a format such as png, which returns a promise resolving to a data URL. The sketch can also be exported as an SVG, which is the native format of the drawing.

### What is the difference between onChange and onStroke in react-sketch-canvas?

onChange returns the current sketch path in the CanvasPath type on every path change, while onStroke returns the last stroke path and whether it is an eraser stroke on every pointer up event. The first is the whole drawing, the second is the individual gesture.

## Sources

- [License: MIT](https://github.com/vinothpandian/react-sketch-canvas/blob/main/LICENSE)
- [Project website](https://vinoth.info/react-sketch-canvas)
- [README](https://github.com/vinothpandian/react-sketch-canvas/blob/main/README.md)
- [Releases](https://github.com/vinothpandian/react-sketch-canvas/releases)
- [vinothpandian/react-sketch-canvas on GitHub](https://github.com/vinothpandian/react-sketch-canvas)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/vinothpandian-react-sketch-canvas
