繁体   English   中英

反应钩子没有从库事件(FabricJS)的回调 function 中返回更新的 state 值

[英]React hooks not returning updated state values inside callback function from library events (FabricJS)

我没有在 FabricJS 事件(如 object:modified、mouse:up 等)中获得更新的 state 值……但我可以在该回调函数中设置 state 值。

当我尝试获取 state 值时,它返回的是初始值,而不是更新后的值。

例子:

const [count, setCount] = useState(0);

初始值为 0。我使用 setCount 将值更新为 1。每当我尝试在回调 function 中获取“计数”时,它都会返回 0 或初始值。

编辑:

我想要实现的是,每当修改 object 时,我都试图保存 FabricJS object(对于撤消,重做操作)。 每当 object 发生变化时,FabricJS 都会触发一个事件并在组件中调用 function。 但我没有得到 state 值。

代码:

function MyFunction()
{
   const [canvasObj, setCanvasObj] = useState({});
   const [state, setCanvasState] = useState('');
   const [undo, setUndo] = useState([]);

   useEffect(() => {

      if(Object.keys(canvasObj).length == 0) {
         var _canvas = new fabric.Canvas('canvas', {
            preserveObjectStacking: true,
         });

         setCanvasObj(_canvas);

         _canvas.on("object:modified", saveState);
      }
   });

   function saveState() {
       console.log(canvasObj); // Returns null even though object initialised
       if (state) { // state value returns null. Due to this, I can't get the existing data and push the current state
          let newState = undo;
          newState.push(state);
          setUndo(newState);
       }
       const tmpState = JSON.stringify(canvasObj);
       setCanvasState(tmpState);
   }
}

这是有关如何在反应组件中保存 canvas state 的一般示例。 您需要一个单独的变量来跟踪 canvas 历史更改:

import React, { useRef, useEffect, useCallback, useState } from "react";
import { fabric } from "fabric";

export default function App() {
  const canvasRef = useRef();
  const [canvas, setCanvas] = useState();
  // Array of objects, that represents canvas state history
  const [canvasHistory, setCanvasHistory] = useState([initialState]);
  const [canvasState, setCanvasState] = useState(initialState);

  const onObjectModified = useCallback(
    e => {
      const newCanvasState = e.target.canvas.toJSON();
      setCanvasState(newCanvasState);
      // Limit history depth
      setCanvasHistory(history => [...history, newCanvasState].slice(-4));
    },
    [setCanvasState, setCanvasHistory]
  );

  useEffect(() => {
    const canvas = new fabric.Canvas(canvasRef.current);
    canvas.loadFromJSON(initialState);

    canvas.on("object:modified", onObjectModified);
    setCanvas(canvas);

    // Don't forget to destroy canvas and remove event listeners on component unmount
    return () => canvas.dispose();
  }, [canvasRef, onObjectModified, setCanvas]);

  const moveHistory = useCallback(
    step => {
      const currentStateIndex = canvasHistory.indexOf(canvasState);
      const prevState = canvasHistory[currentStateIndex + step];
      canvas.loadFromJSON(prevState);
      setCanvasState(prevState);
    },
    [canvas, canvasState, canvasHistory, setCanvasState]
  );

  const onUndo = useCallback(() => moveHistory(-1), [moveHistory]);

  const onRedo = useCallback(() => moveHistory(1), [moveHistory]);

  return (
    <div>
      <button onClick={onUndo} disabled={canvasHistory[0] === canvasState}>
        Undo
      </button>
      <button
        onClick={onRedo}
        disabled={canvasHistory[canvasHistory.length - 1] === canvasState}
      >
        Redo
      </button>
      <canvas ref={canvasRef} width="300" height="300" />
    </div>
  );
}

另外,我在这里做了一个最小的工作示例

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM