reactjs - 为什么我遇到 Uncaught TypeError : Cannot read properties of null (reading 'add' ) on deployment?

标签 reactjs fabricjs use-context

enter image description here

我正在使用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

使用 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/

相关文章:

reactjs - 图像路径很奇怪,部署 Next.js 应用程序后我看不到任何图像

javascript - 无法更改编辑页面上的输入类型值

javascript - 如何删除 Fabric.js 中对象周围的蓝色边框

angular - 使用 Angular 向 Fabric.js 对象添加自定义属性

reactjs - 为什么 useContext() 不返回 Provider 值而是返回初始值?

javascript - 如何通过 useReducer 和 useContext 在 Custom Hooks 中调度操作?

javascript - React setState inside componentDidUpdare 导致超出最大更新深度

node.js - 从 fetchData 返回的 Promise 被忽略

javascript - Fabricjs 防止在 Canvas 边界之外进行自由绘制

reactjs - 在 React Native 中使用多个上下文提供程序的更好方法