0

我使用 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 工作原理的重要一点。

当我想到这一点时,这就是我脑海中出现的流程:

我创建了一个画布,并映射了一组矩形属性。这将创建 4 个矩形。我使用一个返回矩形的包装器组件。

          {rectArray.map((rectangle, index) => {
            return (
              <RectWrapper key={index} rectangle={rectangle} index={index} />
            );
          })}

在 RectWrapper 内部,我创建了一个引用,将其传递给 Rect 的 ref 属性。在 onclick 函数中,当我控制台日志“shapeRef”时,我只在调度被注释掉时才看到引用。如果我取消注释调度,则它显示为空,如果我控制台记录状态,则引用始终为空。

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

也许我正在使用钩子以错误的方式解决这个问题。我只是想保持单击的全局状态,因为另一个文件中的组件将依赖于这种状态。

4

2 回答 2

2

问题正在发生,因为您正在将 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>
  );
}

工作演示

于 2020-04-27T16:49:52.440 回答
0

我认为您不需要创建 ref in RectWrapper,因为onClick只有一个event参数。并且可以在事件中找到被点击元素的 ref:

onClick={(e) => {
    const thisRef = e.target;
    console.log(thisRef );
    ...

这是一个没有 useRef 的工作版本:https ://codesandbox.io/s/peaceful-brook-je8qo

于 2020-04-27T16:50:07.160 回答