ReactJS 将 ref 发送到全局 useContext 状态 (Konva)
ReactJS sending ref to global useContext state (Konva)
我正在使用 useContext 作为全局状态解决方案。我有一个包含我的状态的 Store.jsx 和一个减少状态的 reducer.jsx 。我正在使用 Konva 在 HTML5 Canvas 上创建一些形状。我的目标是当我点击一个形状时,我想更新我的全局状态,参考活动的东西,当我再次点击时,清除参考。
我的完整代码可以在这里找到:
https://codesandbox.io/s/staging-platform-2li83?file=/src/App.jsx
问题:
问题是当我通过形状的 onClick 事件更新全局状态时,它说引用是 'null',但是当我 console.log onClick 中的引用时我可以看到正确的引用。
我想我遗漏了关于 useRef 工作原理的重要一点。
当我想到这个时,我的脑海中出现了这样的流程:
我创建了一个 canvas,并映射了一个矩形属性数组。这将创建 4 个矩形。我使用 returns 一个矩形的包装器组件。
{rectArray.map((rectangle, index) => {
return (
<RectWrapper key={index} rectangle={rectangle} index={index} />
);
})}
在 RectWrapper 内部,我创建了一个引用,将其传递给 Rect 的 ref 属性。在 onclick 函数中,当我控制台日志 'shapeRef' 时,我仅在注释掉 dispatch 时才看到引用。如果我取消注释 dispatch 则它显示为 null,如果我控制台记录状态,则引用始终为 null。
const RectWrapper = ({ rectangle, index }) => {
const shapeRef = React.useRef();
return (
<Rect
x={rectangle.x + index * 100}
y={5}
width={50}
height={50}
fill="red"
ref={shapeRef}
onClick={() => {
console.log("ShapeRef: ");
console.log(shapeRef); // This correctly identifies the rect only when dispatch is uncommented
dispatch({
type: "active_image",
payload: {
index: index,
reference: shapeRef
}
});
}}
/>
);
};
也许我用钩子来解决这个问题。我只是想保持点击内容的全局状态,因为另一个文件中的组件将依赖于此状态。
出现问题是因为您将 RectWrapper 组件创建为 App 组件中的功能组件,导致一次又一次地创建该组件的新引用,因此引用丢失
将您的 RectWrapper 移动到在 App 组件外部声明的单独组件中,并将 dispatch
作为道具传递给它
import React, { useEffect, useContext, useState, Component } from "react";
import { Stage, Layer, Rect, Transformer } from "react-konva";
import { Context } from "./Store.jsx";
import "./styles.css";
const RectWrapper = ({ rectangle, index, dispatch }) => {
const shapeRef = React.useRef();
return (
<Rect
x={rectangle.x + index * 100}
y={5}
width={50}
height={50}
fill="red"
ref={shapeRef}
onClick={() => {
console.log("ShapeRef: ");
console.log(shapeRef);
dispatch({
type: "active_image",
payload: {
index: index,
reference: shapeRef
}
});
}}
/>
);
};
export default function App() {
const [state, dispatch] = useContext(Context);
console.log("Global State:");
console.log(state);
const rectArray = [
{ x: 10, y: 10 },
{ x: 10, y: 10 },
{ x: 10, y: 10 },
{ x: 10, y: 10 }
];
return (
<div className="App">
<Stage height={500} width={500}>
<Layer>
{rectArray.map((rectangle, index) => {
return (
<RectWrapper
dispatch={dispatch}
key={index}
rectangle={rectangle}
index={index}
/>
);
})}
</Layer>
</Stage>
</div>
);
}
我认为您不需要在 RectWrapper
中创建引用,因为 onClick
有一个 event
参数。并且可以在事件中找到被点击的元素的ref:
onClick={(e) => {
const thisRef = e.target;
console.log(thisRef );
...
这是一个没有 useRef 的工作版本:https://codesandbox.io/s/peaceful-brook-je8qo
我正在使用 useContext 作为全局状态解决方案。我有一个包含我的状态的 Store.jsx 和一个减少状态的 reducer.jsx 。我正在使用 Konva 在 HTML5 Canvas 上创建一些形状。我的目标是当我点击一个形状时,我想更新我的全局状态,参考活动的东西,当我再次点击时,清除参考。
我的完整代码可以在这里找到: https://codesandbox.io/s/staging-platform-2li83?file=/src/App.jsx
问题:
问题是当我通过形状的 onClick 事件更新全局状态时,它说引用是 'null',但是当我 console.log onClick 中的引用时我可以看到正确的引用。
我想我遗漏了关于 useRef 工作原理的重要一点。
当我想到这个时,我的脑海中出现了这样的流程:
我创建了一个 canvas,并映射了一个矩形属性数组。这将创建 4 个矩形。我使用 returns 一个矩形的包装器组件。
{rectArray.map((rectangle, index) => {
return (
<RectWrapper key={index} rectangle={rectangle} index={index} />
);
})}
在 RectWrapper 内部,我创建了一个引用,将其传递给 Rect 的 ref 属性。在 onclick 函数中,当我控制台日志 'shapeRef' 时,我仅在注释掉 dispatch 时才看到引用。如果我取消注释 dispatch 则它显示为 null,如果我控制台记录状态,则引用始终为 null。
const RectWrapper = ({ rectangle, index }) => {
const shapeRef = React.useRef();
return (
<Rect
x={rectangle.x + index * 100}
y={5}
width={50}
height={50}
fill="red"
ref={shapeRef}
onClick={() => {
console.log("ShapeRef: ");
console.log(shapeRef); // This correctly identifies the rect only when dispatch is uncommented
dispatch({
type: "active_image",
payload: {
index: index,
reference: shapeRef
}
});
}}
/>
);
};
也许我用钩子来解决这个问题。我只是想保持点击内容的全局状态,因为另一个文件中的组件将依赖于此状态。
出现问题是因为您将 RectWrapper 组件创建为 App 组件中的功能组件,导致一次又一次地创建该组件的新引用,因此引用丢失
将您的 RectWrapper 移动到在 App 组件外部声明的单独组件中,并将 dispatch
作为道具传递给它
import React, { useEffect, useContext, useState, Component } from "react";
import { Stage, Layer, Rect, Transformer } from "react-konva";
import { Context } from "./Store.jsx";
import "./styles.css";
const RectWrapper = ({ rectangle, index, dispatch }) => {
const shapeRef = React.useRef();
return (
<Rect
x={rectangle.x + index * 100}
y={5}
width={50}
height={50}
fill="red"
ref={shapeRef}
onClick={() => {
console.log("ShapeRef: ");
console.log(shapeRef);
dispatch({
type: "active_image",
payload: {
index: index,
reference: shapeRef
}
});
}}
/>
);
};
export default function App() {
const [state, dispatch] = useContext(Context);
console.log("Global State:");
console.log(state);
const rectArray = [
{ x: 10, y: 10 },
{ x: 10, y: 10 },
{ x: 10, y: 10 },
{ x: 10, y: 10 }
];
return (
<div className="App">
<Stage height={500} width={500}>
<Layer>
{rectArray.map((rectangle, index) => {
return (
<RectWrapper
dispatch={dispatch}
key={index}
rectangle={rectangle}
index={index}
/>
);
})}
</Layer>
</Stage>
</div>
);
}
我认为您不需要在 RectWrapper
中创建引用,因为 onClick
有一个 event
参数。并且可以在事件中找到被点击的元素的ref:
onClick={(e) => {
const thisRef = e.target;
console.log(thisRef );
...
这是一个没有 useRef 的工作版本:https://codesandbox.io/s/peaceful-brook-je8qo