I have App.tsx
which contains 2 sibling components:
Konva.tsx
: It has the CanvasOptions.tsx
: It has a Download Canvas button
So I created a ref
named stageRef
in App.tsx
to pass it to Konva.tsx
& Options.tsx
. I use React.forwardRef
to forward refs to child components.
App.tsx
import * as React from 'react'
import type { Stage as StageType } from 'konva/types/Stage'
import { Konva, Options } from '@/components/index'
import { FrameItProvider } from '@/store/index'
const App = () => {
const stageRef = React.createRef<StageType>()
return (
<>
<Konva ref={stageRef} />
<Options ref={stageRef} />
</>
)
}
export default App
In Konva.tsx
, the ref
points to the Canvas so it can access the element in the DOM.
Konva.tsx
import * as React from 'react'
import { observer } from 'mobx-react'
import { useFrameItStore } from '@/store/index'
import { BrowserWindow } from '@/components/index'
import type { Window } from '@/types/index'
import type { Stage as StageType } from 'konva/types/Stage'
interface IProps {
className?: string
}
export const Konva = observer(
React.forwardRef<StageType, IProps>(({ className }: IProps, forwardedRef) => {
const frameItStore = useFrameItStore()
const browser: Window = frameItStore.browser
return (
<>
<Stage
width={browser.width}
height={browser.height}
ref={forwardedRef}
className={className}
>
<Layer>
<BrowserWindow />
</Layer>
</Stage>
</>
)
})
)
In Options.tsx
, I trigger the download call using downloadImage
with the forwardedRef
.
Options.tsx
import * as React from 'react'
import { observer } from 'mobx-react'
import type { Stage as StageType } from 'konva/types/Stage'
import { useFrameItStore } from '@/store/index'
import type { TrafficSignalStyle } from '@/types/index'
interface IProps {
className?: string
}
export const Options = observer(
React.forwardRef<StageType, IProps>((props: IProps, forwardedRef) => {
const frameItStore = useFrameItStore()
const downloadImage: (stageRef: React.ForwardedRef<StageType>) => void =
frameItStore.downloadImage
return (
<div>
<button onClick={() => downloadImage(forwardedRef)}>
Download Canvas
</button>
</div>
)
})
)
I'm using MobX to manage my store. However, the forwardRef
causes problem.
store/index.ts
import type { Stage as StageType } from 'konva/types/Stage'
import type { IFrameItStore } from '@/types/index'
export class FrameItStore implements IFrameItStore {
downloadImage(stageRef: React.ForwardedRef<StageType>) {
console.log(stageRef)
stageRef
.current!.getStage()
.toDataURL({ mimeType: 'image/jpeg', quality: 1 })
}
}
types/index.ts
export interface IFrameItStore {
downloadImage(stageRef: React.ForwardedRef<StageType>): void
}
I get 2 TypeScript errors in store/index.ts
:
TS2531: Object is possibly 'null'.
on stageRef
when I try to access stageRef.current
and
TS2339: Property 'current' does not exist on type '((instance: Stage | null) => void) | MutableRefObject<Stage | null>'.
Property 'current' does not exist on type '(instance: Stage | null) => void'.
on current
I tried not using ForwardedRef
but it gave error that the types do not match so I have to use ForwardedRef
but I'm not sure how to solve this?