我正在使用fabric.js开发一个编辑器应用程序。在本地主机上,当我单击“添加圆”时,它在部署时工作正常,导致无法读取null的属性。
这是代码:
我正在使用 React context api,通过它在 Canvas 中添加对象并将其显示在屏幕上。
FabricCircle.js
import { fabric } from 'fabric';
import ContextCanvas from '../../../context/ContextCanvas';
import { Button } from '@chakra-ui/react';
const FabricTextBox = () => {
const [canvas] = useContext(ContextCanvas);
function addTextBox() {
const textbox = new fabric.Textbox('Click on the Rectangle to move it.', {
fontSize: 20,
left: 50,
top: 100,
width: 200,
fill: 'black',
color: 'white',
cornerColor: 'blue',
});
canvas.add(textbox);
canvas.requestRenderAll();
}
return (
<>
<Button
type="button"
colorScheme="blue"
onClick={addTextBox}
variant={'ghost'}
_hover={{}}
_focus={{}}
_active={{}}
textColor={'white'}
fontWeight={'light'}
>
Text Field
</Button>
</>
);
};
export default FabricTextBox;
FabricCanvas.js
import React, { useContext, useLayoutEffect } from 'react';
import { fabric } from 'fabric';
import ContextCanvas from '../../context/ContextCanvas';
const FabricCanvas = () => {
const [canvas, initCanvas] = useContext(ContextCanvas);
useLayoutEffect(() => {
return () => {
initCanvas(new fabric.Canvas('c'));
};
}, []);
return (
<>
<canvas
id="c"
width={window.innerWidth}
height={window.innerHeight}
/>
</>
)
}
export default FabricCanvas;
ContextCanvas.js
import { fabric } from 'fabric';
const ContextCanvas = createContext();
export function CanvasProvider({ children }) {
const [canvas, setCanvas] = useState(null);
const initCanvas = c => {
setCanvas(c);
c.renderAll();
};
return (
<ContextCanvas.Provider value={[canvas, initCanvas]}>
{children}
</ContextCanvas.Provider>
);
}
export default ContextCanvas;
最佳答案
我认为该错误与 FabricCircle.js
中的这一行有关
canvas.add(textbox);
^^^^
因为你的 Canvas 对象是 null
正在生产。
假设您使用 React.StrictMode
With Strict Mode starting in React 18, whenever a component mounts in development, React will simulate immediately unmounting and remounting the component:
严格模式流程 ( read more )
* React mounts the component.
* Layout effects are created.
* Effect effects are created.
* React simulates effects being destroyed on a mounted component.
* Layout effects are destroyed. [THIS]
* Effects are destroyed.
* React simulates effects being re-created on a mounted component.
* Layout effects are created
* Effect setup code runs
The step marked with
[THIS]
is what makes you feel all right in the local environment (but it's an illusion... See why in the next section).
话虽如此:
您的 Canvas 已初始化null
里面useState
并在 useLayoutEffect
,您正在调用initCanvas
方法内部 cleanup function (因此,只有在生产中为时已晚时才会调用它,而在使用 StrictMode 进行开发时,它就像一个初始化函数,尽管它是一个清理函数)。
useLayoutEffect(() => {
// Your code should be here
return () => { // The returned function is the cleanup function
// This is executed only when disposing the component.
initCanvas(new fabric.Canvas('c'));
// But when strict mode is active
// the component is disposed and re-mounted immidiatly.
};
}, []);
This is why the local environment works and the production environment doesn't.
解决方案
尝试更新您的 useLayoutEffect
像这样:
useLayoutEffect(() => {
initCanvas(new fabric.Canvas('c'));
}, []);
结论
您不应该在清理函数中初始化您的状态。
在本例中,React.StrictMode
行为会阻止您意识到错误(如果没有严格模式,它甚至无法在开发中工作)。
由于您在清理函数中初始化 Canvas ,因此 Canvas 永远不会及时初始化(没有严格模式),剩余 null
,如您收到的错误所示。
关于reactjs - 为什么我遇到 Uncaught TypeError : Cannot read properties of null (reading 'add' ) on deployment?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73032118/