I am trying to draw an image on a canvas using React and Fabric.js.
Demo(CodeSandBox)
In the above demo, when the "Draw image" button is pressed, one would expect an image to be immediately drawn on the canvas, but no image is drawn on the canvas.
The reason why the image is not drawn seems to be that the current of useRef is null when executing the function to draw the image on the canvas.(If the isInput condition on line 50 is removed, containerRef.current is no longer null and the image can be drawn on the canvas.)
Could you help me to draw an image on the canvas?
The code is as follows.
const App = () => {
const [img, setImg] = useState(defaultImg);
const changeImg = ({ target: { value } }: { target: { value: string } }) =>
setImg(value);
const [isInput, setIsInput] = useState(false);
const containerRef = useRef<HTMLDivElement>(null);
const canvasRef = useRef<HTMLCanvasElement>(null);
const checkCurrent = (caller: string) => {
console.log(`[${caller}]Container: ${containerRef.current}`);
};
useEffect(() => {
if (!isInput) return;
checkCurrent("useEffect");
}, [isInput]);
const drawImg = (e: { preventDefault: () => void }) => {
e.preventDefault();
if (!img) return;
setIsInput(true);
checkCurrent("drawImg");
canvas = new fabric.Canvas("canvas");
fabric.Image.fromURL(img, (imgObj: fabric.Image) => {
canvas.add(imgObj).renderAll();
});
};
return (
<div className="App">
{!isInput && (
<form onSubmit={drawImg}>
Demo image url
<input type="text" onChange={changeImg} defaultValue={img} />
<button type="submit">Draw image</button>
</form>
)}
{isInput && (
<>
<button onClick={() => setIsInput(false)}>Reset</button>
<div ref={containerRef} className="canvas_container">
<canvas ref={canvasRef} id="canvas" />
</div>
</>
)}
</div>
);
};
export default App;
I understand that containerRef.current is null if there is no DOM.
However,
- the div to which
containerRefis set is drawn bysetIsInput(true) containerRef.currentobtained insideuseEffectis not null.
From the above points, we can expect that containerRef.current is not null even inside the drawImg function.
