Search code examples
javascriptreactjsp5.js

How not to re-render the canvas once state changes?


I have couple of states where I change on different parts of the project:

which are:

    const [sketchDimensions, setSketchDimensions] = useState(SHOE_DIMENSIONS);
    const [selectedSegment, setSelectedSegment] = useState(null);
    const [activeSidebar, setActiveSidebar] = useState(1);
    
    // and so on 

and I'm using @P5-wrapper/react as a p5 wrapper.

I have a canvas component:

const Canvas = memo(({ sketchDimensions, setSketchDimensions, selectedSegment, setSelectedSegment, activeSidebar, selectedView, currentView }) => {
    if (sketchDimensions.length > 0) {
        console.log('initialized canvas');

        return (
            <ReactP5Wrapper
                sketch={shoeSketch}
                sketchDimensions={sketchDimensions}
                setSketchDimensions={setSketchDimensions}
                selectedSegment={selectedSegment}
                setSelectedSegment={setSelectedSegment}
                // and others
            />
        );
    }
});

I have updateWithProps like following:

    p5.updateWithProps = props => {
        if (props.sketchDimensions !== dataDimensions) {
            dataDimensions = props.sketchDimensions;
        }
        if (props.setSketchDimensions !== setDataDimensions) {
            setDataDimensions = props.setSketchDimensions;
        }

        if (props.selectedSegment !== initVariables.selectedSegment) {
            initVariables.selectedSegment = props.selectedSegment;
        }
    };

and problem appears when the state changes and it creates new canvas elements and GPU increases around 0.8-0.9GB every time one of the states change.

task manager

is it possible not to re-render the canvas every time state changes?


Solution

  • According to devs, it seems to be wrapper's behaviour, so I had to change the logic a bit.

    In ThreeJS there is a renderer.forceContextLoss which actually prevents to have too many contents (for more information check here) and in p5 we can use .remove() function.

    Additionally, as in our case sketchDimensions and other states change and with the wrapper it redraws and adds to GPU, we had to change the logic to use functions for specific parts.

    Like:

    export const changeActiveSidebar = (activeSidebar) => {
        initVariables.activeSidebar = activeSidebar;
    }
    

    with this method it does not recreate the canvas (might sound weird, but it indeed works).