如何解决React Konva 在兄弟组件之间共享引用抛出错误
我有 App.tsx
,其中包含 2 个兄弟组件:
-
Konva.tsx
:它有画布 -
Options.tsx
:它有一个下载画布按钮
因此我在 ref
中创建了一个名为 stageRef
的 App.tsx
以将其传递给 Konva.tsx
和 Options.tsx
。我使用 React.forwardRef
将引用转发给子组件。
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
在 Konva.tsx
中,ref
指向 Canvas,以便它可以访问 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>
</>
)
})
)
在 Options.tsx
中,我使用 downloadImage
和 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>
)
})
)
我正在使用 MobX 来管理我的商店。但是,forwardRef
会导致问题。
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 })
}
}
类型/index.ts
export interface IFrameItStore {
downloadImage(stageRef: React.ForwardedRef<StageType>): void
}
我在 store/index.ts
中遇到 2 个 TypeScript 错误:
TS2531:对象可能为“空”。
在 stageRef
当我尝试访问 stageRef.current
和
TS2339: Property 'current' does not exist on type '((instance: Stage | null) => void) | MutableRefObject<Stage | null>'.
属性 'current' 在类型 '(instance: Stage | null) => void' 上不存在。
在current
我尝试不使用 ForwardedRef
但它给出了类型不匹配的错误,所以我必须使用 ForwardedRef
但我不知道如何解决这个问题?
解决方法
我在 ref
中创建了一个 App.tsx
,然后将其传递给 Konva.tsx
。我使用 React.forwardRef
函数捕获了 ref。
然后我使用 useImperativeHandle
中鲜为人知的 Konva.tsx
钩子访问 downloadImage
中的函数 App.tsx
,然后将函数 downloadImage
直接传递给 {{ 1}}。
我没有在 MobX 商店中保存任何东西。只需将它本地保存在易于访问的 Options.tsx
组件中。旧规则是,如果不打算在任何其他组件中使用它,则应使其尽可能靠近该组件。
App.tsx
Konva
Konva.tsx
import * as React from 'react'
import { Konva,Options } from '@/components/index'
const App = () => {
const stageRef = React.useRef<{ downloadImage: Function }>(null)
return (
<>
<Konva ref={stageRef} />
<Options downloadImage={() => stageRef?.current?.downloadImage()} />
</>
)
}
export default App
Options.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
}
interface ForwardedRef {
downloadImage: Function
}
export const Konva = observer(
React.forwardRef<ForwardedRef,IProps>(
({ className }: IProps,forwardedRef) => {
const frameItStore = useFrameItStore()
const browser: Window = frameItStore.browser
const stageRef = React.useRef<StageType>(null)
React.useImperativeHandle(
forwardedRef,() => ({
downloadImage: () =>
stageRef.current
?.getStage()
.toDataURL({ mimeType: 'image/jpeg',quality: 1 }),}),[]
)
return (
<Stage
width={browser.width}
height={browser.height}
ref={stageRef}
className={className}
>
<Layer>
<BrowserWindow />
</Layer>
</Stage>
)
}
)
)
这是关于 CodeSandBox 的完整工作演示 → https://codesandbox.io/s/react-konva-share-refs-between-siblings-dsd97?file=/src/App.tsx
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。