Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

State is not updating in react #2447

Open
SuhaibMaraqa opened this issue Dec 21, 2023 · 4 comments
Open

State is not updating in react #2447

SuhaibMaraqa opened this issue Dec 21, 2023 · 4 comments
Labels

Comments

@SuhaibMaraqa
Copy link

I am using OSD in React, whenever I use a react state inside the OSD code it keeps giving me the initial state without updating it. how to implement it in a react "friendly way" ?

import * as Annotorious from "@recogito/annotorious-openseadragon";
import Image from "next/image";
import OpenSeaDragon from "openseadragon";
import { useEffect, useRef, useState } from "react";

import "@recogito/annotorious-openseadragon/dist/annotorious.min.css";

const OSD = () => {
  const [viewer, setViewer] = useState<any>(null);
  const [anno, setAnno] = useState<any>(null);
  const annoRef = useRef(null);
  // Current drawing tool name
  const [tool, setTool] = useState("rect");

  const InitOpenseadragon = () => {
    let annotorious: any = null;

    if (viewer) {
      viewer.destroy();
    }

    if (anno) {
      anno.destroy();
    }

    const osdViewer = OpenSeaDragon({
      animationTime: 0.5,
      blendTime: 0.1,
      constrainDuringPan: true,
      gestureSettingsMouse: { clickToZoom: false },
      id: "openSeaDragon",
      maxZoomPixelRatio: 5,
      prefixUrl: "//openseadragon.github.io/openseadragon/images/",
      tileSources: {
        type: "image",
        url: "",
      },
    });

    const config = {
      allowEmpty: true,
      disableEditor: true,
      drawOnSingleClick: true,

      //   hotkey: { inverted: true, key: "Shift" },
    }; // Optional plugin config options

    annotorious = Annotorious(osdViewer, config);

    setAnno(() => annotorious);

    annoRef.current = annotorious;

    osdViewer.addHandler("open", () => {
      const toggleDraw = new OpenSeaDragon.Button({
        onClick: () => {
          //here the tool is maintaining the initial state of rect and it is not updating
          console.log("onClick", tool);

          toggleTool(annotorious, tool);
        },
        srcDown: "/images/zoomin_rest.png",
        srcGroup: "/images/zoomin_rest.png",
        srcHover: "/images/zoomin_rest.png",
        srcRest: "/images/zoomin_rest.png",
        tooltip: "Change Drawing Tool",
      });

      osdViewer.addControl(toggleDraw.element, {
        anchor: OpenSeaDragon.ControlAnchor.TOP_LEFT,
      });
    });

    setViewer(osdViewer);
  };

  useEffect(() => {
    InitOpenseadragon();

    return () => {
      if (viewer) {
        viewer.destroy();
      }

      if (anno) {
        anno.destroy();
      }
    };

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Toggles current tool + button label
  const toggleTool = (annotorious: any, drawingTool: string) => {
    console.log(tool);

    if (!annotorious) {
      return;
    }

    if (tool === "rect") {
      setTool(() => "polygon");
      annotorious.setDrawingTool("polygon");
    } else {
      setTool(() => "rect");
      annotorious.setDrawingTool("rect");
    }
  };

  useEffect(() => {
    console.log("tool", tool);
  }, [tool]);

  return (
    <>
      <div
        id="openSeaDragon"
        style={{
          bottom: 0,
          height: "100vh",
          position: "fixed",
          right: 0,
          width: "50vw",
        }}
      >
        <h2 style={{}}>Press Shift to draw annotations</h2>
      </div>
    </>
  );
};

export default OSD;
@iangilman
Copy link
Member

What if you do the OSD manipulation outside of the React state system? OSD keeps its own state.

@SuhaibMaraqa
Copy link
Author

one way around it is the useRef hook, as you said OSD keeps its own state so on initialization it get all the current state values and keeps it as it is and if any change happens it won't reflect on OSD

@iangilman
Copy link
Member

Sounds like a decent strategy.

@abiswas97
Copy link

@SuhaibMaraqa bit late, but hopefully this helps - we use OSD in react as well, and use a redux slice to store a pointer to the OSD instance.

OSD has a getViewer static method, that returns the entire instance - this has worked really well for us, and we don't need to duplicate OSD's state in react specific ways.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants