在 Mobx 中监听 Window Resize 事件不更新 React Konva 中 Stage 组件的宽度和高度

Listening to Window Resize event in Mobx not updating Stage component's width & height in React Konva

我在 Mobx 中有一个可观察的 win,它会在 window 调整大小时更新。 updateWin 函数更新 win observable。

FrameItStore.tsx

import { makeObservable, observable, action, computed } from "mobx";

import { Point, TrafficSignalPosition, IFrameItStore } from "@/types/index";

export class FrameItStore implements IFrameItStore {
  id = 0;
  win = {
    width: window.innerWidth,
    height: window.innerHeight
  };
  box = {
    width: 1024,
    height: 600
  };
  trafficSignalColors = [
    {
      close: "#EF4444",
      minimize: "#FBBE25",
      maximize: "#49DE80"
    },
    {
      close: "black",
      minimize: "blue",
      maximize: "orange"
    }
  ];

  constructor() {
    makeObservable(this, {
      win: observable,
      updateWin: action.bound,
      box: observable,
      boxCenter: computed,
      trafficSignalPosition: computed,
      trafficSignalColors: observable,
      id: observable
    });

    window.addEventListener("resize", this.updateWin);
  }

  updateWin() {
    this.win.width = window.innerWidth;
    this.win.height = window.innerHeight;
  }

  destroyWin() {
    window.removeEventListener("resize", this.updateWin);
  }

  get boxCenter(): Point {
    return {
      x: (this.win.width - this.box.width) / 2,
      y: (this.win.height - this.box.height) / 2
    };
  }

  get trafficSignalPosition(): TrafficSignalPosition {
    return {
      close: { x: this.boxCenter.x + 20, y: this.boxCenter.y + 20 },
      minimize: { x: this.boxCenter.x + 2 * 20, y: this.boxCenter.y + 20 },
      maximize: { x: this.boxCenter.x + 3 * 20, y: this.boxCenter.y + 20 }
    };
  }
}

width & height 在商店中更新,但我在组件中看不到效果。

如果我将 console.log(this.win) 放在 updateWin 函数中,它会显示更新后的值。但是我在组件中看不到更新的值。

我已经添加了另外 2 个 console.log 语句。

URLBar.tsx

import * as React from "react";
import { Rect } from "react-konva";

import { useFrameItStore } from "../store/index";

import { TrafficSignalPosition, Window } from "../types/index";

export const URLBar = () => {
  const frameItStore = useFrameItStore();
  console.log("URLBar.tsx =►", frameItStore.win.width);

  const box: Window = frameItStore.box;
  const trafficSignalPosition: TrafficSignalPosition =
    frameItStore.trafficSignalPosition;

  return (
    <Rect
      x={trafficSignalPosition.maximize.x + 20}
      y={trafficSignalPosition.maximize.y}
      width={box.width - 3 * 20}
      height={20}
      fill="white"
    />
  );
};

Konva.tsx

import * as React from "react";
import { Stage, Layer } from "react-konva";

import { FrameItContext } from "../store/index";
import { BrowserWindow, SiteImage, TrafficSignal, URLBar } from "./index";

import { Stage as StageType } from "konva/types/Stage";

export class Konva extends React.Component {
  static contextType = FrameItContext;
  context!: React.ContextType<typeof FrameItContext>;

  stageRef = React.createRef<StageType>();

  handleExportClick = () => {
    console.log(
      this.stageRef
        .current!.getStage()
        .toDataURL({ mimeType: "image/jpeg", quality: 1 })
    );
  };

  render() {
    const { win } = this.context;
    console.log("Konva.tsx -►", win.width);

    return (
      <>
        <Stage width={win.width} height={win.height} ref={this.stageRef}>
          <Layer>
            <BrowserWindow />
            <URLBar />
            <TrafficSignal />
            <SiteImage />
          </Layer>
        </Stage>
        <button
          style={{ position: "absolute", top: "0" }}
          onClick={this.handleExportClick}
        >
          Download Image
        </button>
      </>
    );
  }
}

但是 console.log 的 none 再次打印。它也不会更新我的 Konva Stagewidthheight,因此 Stage 变得有响应。

我错过了什么吗?制作了一个 Minimal CodeSandBox here。请注意控制台,它不会更改值。

您需要将您的组件包装到 observer 装饰器中以使其与 MobX 一起工作

import { observer } from "mobx-react";

class KonvaComponent extends React.Component {
  // ..
}

export const Konva = observer(KonvaComponent)

或者如果你使用装饰器建议:

import { observer } from "mobx-react";

@observer
export class Konva extends React.Component {
  // ..
}