React 挂钩不从库事件(FabricJS)的回调函数中返回更新的状态值
React hooks not returning updated state values inside callback function from library events (FabricJS)
我没有在 object:modified、mouse:up 等 FabricJS 事件中获取更新的状态值...但是我可以在回调函数中设置状态值。
当我尝试获取状态值时,它返回的是初始值而不是更新后的值。
示例:
const [count, setCount] = useState(0);
初始值为 0。我使用 setCount 将值更新为 1。每当我尝试在回调函数中获取 "count" 时,它返回 0 或初始值。
编辑:
我想要实现的是,每当对象被修改时(对于撤消、重做操作),我都试图保存 FabricJS 对象。每当一个对象发生变化时,FabricJS 就会触发一个事件并调用组件中的一个函数。但是我没有得到状态值。
代码:
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);
}
}
这是关于如何在 React 组件中保存 canvas 状态的一般示例。您需要一个单独的变量来跟踪 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>
);
}
此外,我做了一个最小的工作示例here
我没有在 object:modified、mouse:up 等 FabricJS 事件中获取更新的状态值...但是我可以在回调函数中设置状态值。
当我尝试获取状态值时,它返回的是初始值而不是更新后的值。
示例:
const [count, setCount] = useState(0);
初始值为 0。我使用 setCount 将值更新为 1。每当我尝试在回调函数中获取 "count" 时,它返回 0 或初始值。
编辑:
我想要实现的是,每当对象被修改时(对于撤消、重做操作),我都试图保存 FabricJS 对象。每当一个对象发生变化时,FabricJS 就会触发一个事件并调用组件中的一个函数。但是我没有得到状态值。
代码:
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);
}
}
这是关于如何在 React 组件中保存 canvas 状态的一般示例。您需要一个单独的变量来跟踪 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>
);
}
此外,我做了一个最小的工作示例here