Search code examples
reactjsfabricjs

FabricJS deserialization issue


I have serialized canvas object, which I get via canvas.toJSON() and after deserialization canvas.loadFromJSON(jsonObj, canvas.renderAll.bind(canvas)) I can't manipulate objects in canvas, they are not selectable.

Expecting behavior: After deserialization all objects have to be selectable and manageable like before serialization.

I reproduced issue in codesandbox

How to reproduce:

  1. Click SERIALIZE
  2. Click DESERIALIZE
  3. Try to grab, rotate or change size of lower image

Maybe I'm doing something wrong? Will be glad to any help and advise.


Solution

  • After some research I found out what was a problem.

    Why I couldn't manipulate deserialized object? Because there were 2 canvas html elements. As we can see from screenshot, there are 2 canvases. First one (green border) with image and the second (red border) is empty. And all my interaction was with empty (red) canvas. If I delete second canvas I can interact with image object. enter image description here

    Why did it happen? In StrictMode callback of useEffect calls twice and that's why I get nested canvas html elements.

    How to fix it? There are several workaround options to get rid off it.

    1. Remove StrictMode. Obvious and simple, but unwanted solution.
    2. Use flag variable outside of component.
    let wasCalled = false;
    export default function App() {
    // ...
    useEffect(() => {
      if (wasCalled) {
        return;
      }
      wasCalled = true;
    // ...
    },[])
    

    May be there are more elegant solutions like initialize instance of canvas in other way, but currently it's ok for me.