0

Fabric.js is a framework that allows a canvas being used for various of things such as free hand drawing, SVG editing, adding text ext.

When I want to create an app that utilizes Fabric for the canvas functionality, I get stuck in the React principle of passing props down and lifting the state up.

Normally I'd want to create a component that provides the canvas with initializing Fabric on it like this:

componentDidMount() {

    this.theCanvas = new fabric.Canvas('main-canvas', {
        preserveObjectStacking: true
    })
}

some local variable gets assigned a fabric.Canvas object, after it mounted a canvas with the id="main-canvas" into the app.

render() {

    return (
        <React.Fragment>
            <div id="canvas-container">
                <canvas style={{border: 'solid 1px #555'}} id='main-canvas' />
            </div>
        </React.Fragment>
    );

Additionally I'd construct some kind of UI elements like a toolbar, tool-settings, export buttons, undo/redo ect.

Exemplary a draw-button that toggles drawMode for the canvas.

render() {
    return(
        <Button
            onClick={this.props.toggleDraw}
            style={{
                backgroundColor: this.props.drawMode ? 'red' : 'blue'
            }}
        >
            Freehand
        </Button>
    );
}

The problem is now, that Fabric needs to be told about this drawMode set to true or disabled when set to false:

    this.the_canvas.isDrawingMode = this.props.drawMode;

The the_canvas.isDrawingMode sets the currently Fabric canvas object, that exists in the Fabric component into drawing.

Now I want to know how I organize this in the best way.

  1. I could get rid of the Fabric component and initialize it in the Root component, here App.js. A toolbar component could pass the state all the way up into App.js and toggle the setting there. I would prefer not to do this since it makes the whole app less modular.

  2. Use a store like Redux, MobX or React.Context for this matter to provide a global state so every toolbar element can have direct access to theCanvas.

  3. I could remove the fabric.Canvas initialization completely from the React UI and include it directly into the root HTML file the traditional way then constructing wrapper functions in the UI elements.

To generalize my question, since this problem is not limited to a thing like Fabric.Js but to any case where I want to use a library that provides external functionality into a React app, what's the best practice to use here?

There are react modules that provide fabric into my app but all I found, like "react-fabricjs" that have been suggested in similar questions here, are several years old and not maintained anymore so I don't want to use them at all.

user6329530
  • 596
  • 1
  • 7
  • 21
  • it may help you https://stackoverflow.com/a/39151456/5124488 – blueseal Nov 04 '19 at 08:59
  • 1
    @blueseal The example uses keyMirror which has it's last commit on npmjs 5 years ago and stuck in version 0.1.1. It's using nuclear-js which was abandoned 3 years ago. It's also not using ES6 syntax but createClass which was removed from React 16. I would rather not prefer to use old modules that are not maintained anymore. – user6329530 Nov 04 '19 at 09:31

0 Answers0