在 React 类组件中使用 Mobx Store 的值?

问题描述

我想访问 React 类组件中的 Hook。

Konva.tsx

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

import { useFrameItStore } from "../store/index";
import { browserWindow,SiteImage,TrafficSignal,URLBar } from "./index";

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

export class Konva extends React.Component {
  stageRef = React.createRef<StageType>();

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

  render() {
    // const frameItStore = useFrameItStore();
    const win: Window = { width: 800,height: 600 }; // frameItStore.win;

    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>
      </>
    );
  }
}

我想使用上面代码中注释的 useFrameItStore() 钩子来设置 width & height

store/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,Box: observable,BoxCenter: computed,trafficSignalPosition: computed,trafficSignalColors: observable,id: observable
    });

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

  updateWin() {
    if (typeof window === "object") {
      console.log(this.win);
      console.log(window.innerWidth);
      console.log(window.innerHeight);
      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,maximize: { x: this.BoxCenter.x + 3 * 20,y: this.BoxCenter.y + 20 }
    };
  }
}

store/FrameItContext.tsx

import * as React from "react";
import { useLocalObservable } from "mobx-react";

import { FrameItStore } from "./index";

import { IFrameItStore } from "../types/index";

const FrameItContext = React.createContext<IFrameItStore>(new FrameItStore());

// export const FrameItProvider = ({ children }: { children: React.ReactChild }) => {
//  const frameItStore = useLocalObservable(() => new FrameItStore())

//  return <FrameItContext.Provider value={frameItStore}>{children}</FrameItContext.Provider>
// }

export const useFrameItStore = () => React.useContext(FrameItContext);

但是,我不能在 Class 组件中使用 Hook。我已经制作了一个完整的沙盒 → https://codesandbox.io/s/frameit-mobx-konva-ns62n

如何访问 Konva.tsx 文件中的商店?

解决方法

您可以设置 contextType on a class component 以访问 this.context 上的上下文值。

export class Konva extends React.Component {
  // ...

  static contextType = FrameItContext;
  context!: React.ContextType<typeof FrameItContext>;

  render() {
    const { win } = this.context;

    // ...
  }
}
,

为什么不将宽度和高度添加为可观察值的一部分,然后根据需要更改 FrameItStore.tsx 中的值。