Saving the reference of a Fabric.js Canvas in Vuex - [vuex] refrain from altering the vuex store state outside of mutation handlers

I'm developing a Vue Application that utilizes Fabric.js to manage the canvas element.

My goal is to control the canvas state through Vuex. To achieve this, I have assigned the fabric canvas instance to a Vuex state variable.

Mutation

setCanvas(state, canv) {
    state.canvas = canv
  }

Within Vue Component

const canvas = new fabric.Canvas('main-canvas')
this.setCanvas(canvas) //execute the mutation

In another mutation, my task is to add an object to the canvas:

addLayer(state, layer) {
    state.canvas.add(layer)
 }

Upon executing this mutation, I encounter the following error:

[vuex] do not mutate Vuex store state outside mutation handlers.

My theory is that the fabric.js instance is modifying its properties internally, which Vuex does not permit.

What would be the most effective approach to resolve this issue and properly store the fabric object? Alternatively, is there a more efficient solution available?

Answer №1

Storing it in the vuex may not be the most optimal solution, but I understand why you might consider doing so. Perhaps because multiple components throughout your app need access to the canvas methods.

It appears that storing it in Vuex copies over events that trigger mutations outside of the mutation handler, which can lead to unintended consequences.

You might want to consider handling all canvas initialization in a single component (using the "mounted" method), and then use Vuex state watches to track events like when a button is clicked to add a circle. This way, you can respond to these events within the component itself. This is how I've approached similar situations in the past. I'll update if I come across a better approach.

If you have discovered a more effective method, please feel free to share.

Answer №2

When working with Vue3, I will utilize the provide/inject feature to establish a global property:

In the main.js file:

// src/main.js
import { createApp, reactive } from 'vue'
import App from './App.vue'

const globalProperties = {'canvas': null}; 

const app = createApp(App);
app.provide('globalProperties', globalProperties)
app.mount('#app');

This property must be injected into all components where it will be used like this

export default {  
  inject: ['globalProperties'],
  ...

It can then be accessed in the script using this.globalProperties. For example, in the component containing the <canvas \> tag, you can initialize this.globalProperties.canvas in the mounted function as follows:

  mounted() { 
    this.globalProperties.canvas = new fabric.Canvas('main-canvas')
    ...

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

When attempting to display a sub view in Express, a 404 error is encountered

I am currently working with express and jade to display a web page. My intention is to render the page using this format 'http://127.0.0.1:5000/services/landfreight' but I keep encountering a 404 error. router.get('/service/landfreight' ...

Node.js used to create animated gif with unique background image

As I navigate my way through the world of node.js and tools like express and canvas, I acknowledge that there might be errors in my code and it may take me some time to grasp certain concepts or solutions. My current project involves customizing a variati ...

Issue with accessing Protractor spec file location

As a newcomer to Protractor, I followed a tutorial on GitHub to set everything up. The tutorial was successful, but when I tried to apply it to my actual code, I encountered a problem. I found that I can only call the spec.js file if it's located in t ...

Adjust the size of the leaflet popup with Vue2Leaflet's l-popup component

I've been working on programming a web application and incorporating leaflet to showcase a map. I've set up markers and popups that show up when the markers are clicked. However, I've noticed that the popups look a bit odd right now – the ...

How can you access a sibling of the parent element of the current element in Jquery?

I'm working on an HTML project where I have a select field. Depending on the option selected, I need to update the price field with the corresponding price fetched using Ajax. Additionally, I want to be able to input multiple rows by clicking on the ...

Changing UUID from binary to text and vice versa in NodeJS

I recently started a project that transitioned to using MySQL as our database. We are working with UUID strings (such as 43d597d7-2323-325a-90fc-21fa5947b9f3), but the database field is defined as binary(16) - a 16-byte unsigned binary. Although I know th ...

The problem with escaping characters in Javascript occurs when a backslash is duplicated within an object

My intention was to save the JSON object with an escape character by escaping "/". I achieved this by using string replace to convert my string into "\/". Afterwards, I assigned this to an object variable and attempted to console log it, only to find ...

What is the best way to modify the color of an individual row in an HTML table by simply clicking a button within that specific

this is my unique table content echo"<table id=\"unique_company\">"; while($row=mysql_fetch_array($res)) { $s= $row['company_id']; $r= $row[&a ...

Exploring the occurrence of immutation within nested arrays inside objects

let myObject = {key : 'Add', array : [0, 2, 3]} let clonedObject = Object.assign({}, myObject, {array: myObject.array}) clonedObject.array.pop() console.log(myObject) console.log(clonedObject) In the above example, let's say we want to rem ...

What is the best way to extract menu and submenu information from an array?

I'm in the process of building a webpage with the help of smart admin and I'm facing an issue with displaying left menu data properly. The data is being retrieved from an array and I need to arrange the menus and submenus based on the parent ID o ...

I am looking to develop a unique event that can be triggered by any component and listened to by any other component within my Angular 7 application

Looking to create a unique event that can be triggered from any component and listened to by any other component within my Angular 7 app. Imagine having one component with a button that, when clicked, triggers the custom event along with some data. Then, ...

Using JavaScript to open a fresh window (Google Maps), eliminating the previous event handler

Attempting to implement geolocation using a combination of HTML and javascript. The goal is to obtain the user's location and then open a new tab redirecting to Google Maps with directions displayed. User's current location serves as the starting ...

The link and source attributes are missing from the .ejs template

I am experiencing an issue where the href and src attributes in my .ejs file are not referencing my local files properly. My setup involves node.js and express. Here is a snippet from the .ejs template that is causing the problem. <head> & ...

The usage of ngRoute clashes with the functionality of Animated Scroll

I am experiencing a conflict between my ng-route and the animated scroll feature on my website: Below is the code for my scroll element: <a href="#one" class="goto-next scrolly">Next</a> In this code, "#one" represents the section ID to scro ...

elevate the div with a floating effect

My goal is to create a chat feature for users that will only be visible for a limited time period. I was thinking of using PHP and timestamp to achieve this functionality, but I also want to make the chat visually disappear by having the message div float ...

Encountered an Angular 1.6 Error: The requested URL at http://127.0.0.1:56035/[url] could not be found (404

I've hit a roadblock in my project and can't seem to figure out the issue. The file I'm working on is supposed to display an iframe video player with a YouTube embed. I tried using interpolation to construct the correct URL: <div class= ...

Rendering HTML is not supported by AngularJS on Android 19 with version 4.4.4 and Safari 8.0.5

I have been working on an AngularJS app that is being displayed in a Webview on Android. Everything was functioning properly until yesterday when I started encountering issues with Angular not rendering the DOM correctly. I have tested the app on various v ...

I am having trouble getting the color, metalness, lights, and shaders to work properly in Three JS on my

I attempted to create a simple code using Three.js for a red colored torus with a point light and a textured surface, but unfortunately, all I achieved was a black torus that rotates. It seems like the elements in this code are not functioning as expecte ...

Is it possible to merge node modules that have similar functionalities?

When utilizing node.js, you may encounter module dependencies containing functions with similar functionalities, such as underscore, lodash, and lazy (potentially in different versions). Is there a way to specify which module from a group of similar metho ...

Develop a fresh AngularJS directive that utilizes the HTML5 audio element

Recently delved into Angular and managed to create audio buttons using an Angular directive: app.directive('soundButton', [function () { return { restrict: 'E', link: function (scope, element, attrs) { v ...