enter image description here

我正在使用fabric开发一个编辑器应用程序.js.在localhost上,当我单击Add Circle时,它可以正常工作,而在部署时,它会导致无法读取null的属性.

代码如下:

我正在使用react-context api,通过该api,我在画布中添加对象,并将其显示在屏幕上.

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);
      ^^^^

因为画布对象是null in production.


Assuming you use React.StrictMode

使用React.StrictMode

从React 18开始的严格模式下,每当组件在开发中安装时,React将立即模拟卸载和重新安装组件:

Strict mode flow (100)

* 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 100 is what makes you feel all right in the local environment (but it's an illusion... See why in the next section).


With that been said:

画布在useState中初始化null,在useLayoutEffect中调用initCanvas方法inside the cleanup function(因此,只有在生产中太晚时才会调用它,而在使用StrictMode开发时,它就像init函数一样,尽管它是一个清理函数).

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.
    };
}, []);

这就是为什么本地环境起作用而生产环境不起作用.

解决方案

Try updating your 100 like this:

useLayoutEffect(() => {
   initCanvas(new fabric.Canvas('c'));
}, []);

结论

不应在清理函数内初始化状态.

在这种情况下,React.StrictMode行为会阻止您意识到错误(without strict mode, it wouldn't even work in development).

由于您在cleanup函数内初始化画布,画布永远不会及时初始化(没有严格模式),剩余null,作为您收到的错误状态.

Reactjs相关问答推荐

为什么VScode中的React应用程序无法识别文件夹 struct ?

For循环中的元素在Reaction中丢失挂钩

获取点击的国家/地区名称react 映射

React,React Router,Joy UI:如何在导航离开和返回后禁用snackbar重新出现?

React中的useEffect钩子

无法在主组件的返回语句中呈现预期组件

如何解决Reaction中遗留的上下文API错误?

用于获取带有事件处理程序的API的动态路由

MUI:在props 主题中找到的值:;错误;是[Object],而不是字符串或数字

console.logs 没有显示在浏览器控制台上,但显示在我的终端上

这个简单的React组件为什么会多次渲染?

如何避免在 react useEffect 上滚动时出现小的延迟?

添加 React/Redux 组件模板的 VS Code 扩展

React Router v6 - 访问嵌套路由和处理手写 url 的正确方法

如果查询不存在,如何返回所有产品?

无法重用我的组件,它只显示 1 次

NextJs - 如何从站点 map 生成器中删除重复的 URL?

在react 路由dom版本6中的组件内添加路由

RTK 查询 POST 方法不会改变数据

警告:您在没有 `onChange` 处理程序的情况下为表单字段提供了 `value` 属性