Estoy usando reaccionar con mecanografiado. En mi proyecto, intento dibujar varios rectángulos en mi SVG. El primer rectángulo se dibuja fácilmente, pero cuando intento dibujar otro rectángulo, el anterior desaparece y luego se dibuja el nuevo. ¿Cómo mantengo el rectángulo dibujado previamente en un estado y luego lo renderizo?
enlace sandbox completo aquí está mi código:
const svgRef = useRef<SVGSVGElement>(null); const divRef = useRef<HTMLDivElement>(null); const { xCord, yCord } = useMousePosition({ divRef }); const [mousedown, setMouseDown] = useState(false); const [last_mousex, set_last_mousex] = useState(0); const [last_mousey, set_last_mousey] = useState(0); const [mousex, set_mousex] = useState(0); const [mousey, set_mousey] = useState(0); const [rectx, setrectx] = useState(0); const [recty, setrecty] = useState(0); const [rectwidth, setrectwidth] = useState(0); const [rectheight, setrectheight] = useState(0); const mouseDown = () => { set_last_mousex(xCord); set_last_mousey(yCord); setMouseDown(true); }; const mouseUp = () => { setMouseDown(false); }; const mouseMove = () => { set_mousex(xCord); set_mousey(yCord); }; const addRectangle = () => { if (mousedown) { const width = Math.abs(mousex - last_mousex); const height = Math.abs(mousey - last_mousey); const rx = mousex < last_mousex ? mousex : last_mousex; const ry = mousey < last_mousey ? mousey : last_mousey; rectx!==rx && setrectx(rx); recty!==ry && setrecty(ry); rectheight!==height && setrectheight(height); rectwidth!==width && setrectwidth(width); return ( <rect x={rx} y={ry} height={height} width={width} /> ); } }; return ( <div className="App" ref={divRef}> <svg id="svg" ref={svgRef} onMouseDown={mouseDown} onMouseUp={mouseUp} onMouseMove={mouseMove} > {addRectangle() ? ( addRectangle() ) : ( <rect x={rectx} y={recty} height={rectheight} width={rectwidth} /> )} </svg> </div> );Puedo ver varios problemas con su código:
está llamando al evento mouseDown y configurando el estado, pero está usando addRectangle para su condición en lugar de simplemente llamarlo como una función. En la mayoría de los casos, esto presentará problemas de condición de carrera.
luego devuelve addRectangle() en lugar de agregarlo en una matriz, esta es la razón por la cual se reemplaza el rectángulo anterior.
Lo que sugiero es:
const svgRef = useRef<SVGSVGElement>(null); const divRef = useRef<HTMLDivElement>(null); const { xCord, yCord } = useMousePosition({ divRef }); const [last_mousey, set_last_mousey] = useState(0); const [mousex, set_mousex] = useState(0); const [mousey, set_mousey] = useState(0); const [rectx, setrectx] = useState(0); const [recty, setrecty] = useState(0); const [rectwidth, setrectwidth] = useState(0); const [rectheight, setrectheight] = useState(0); const [rects, setRects] = useState([]); const mouseDown = () => { setRects(rects.concat(addRectangle(xCord, yCord))); }; const mouseMove = () => { set_mousex(xCord); set_mousey(yCord); }; const addRectangle = (last_mousex, last_mousey) => { const width = Math.abs(mousex - last_mousex); const height = Math.abs(mousey - last_mousey); const rx = mousex < last_mousex ? mousex : last_mousex; const ry = mousey < last_mousey ? mousey : last_mousey; rectx!==rx && setrectx(rx); recty!==ry && setrecty(ry); rectheight!==height && setrectheight(height); rectwidth!==width && setrectwidth(width); return ( <rect x={rx} y={ry} height={height} width={width} /> ); }; return ( <div className="App" ref={divRef}> <svg id="svg" ref={svgRef} onMouseDown={mouseDown} onMouseMove={mouseMove} > {rects.length > 0 ? ( rects.map(rect => rect) ) : ( <rect x={rectx} y={recty} height={rectheight} width={rectwidth} /> )} </svg> </div> );last_mousex , mousedown y last_mousey y los pasé directamente.mouseDown y eliminé mouseUp , deberían hacer lo mismo.rects para que sean una matriz.Puedes lograrlo así
const [rectArray, setRectArray] = useState<Array<JSX.Element>>([]); const addRectangle = () => { if (mousedown) { const width = Math.abs(mousex - last_mousex); const height = Math.abs(mousey - last_mousey); const rx = mousex < last_mousex ? mousex : last_mousex; const ry = mousey < last_mousey ? mousey : last_mousey; rectx !== rx && setrectx(rx); recty !== ry && setrecty(ry); rectheight !== height && setrectheight(height); rectwidth !== width && setrectwidth(width); setRectArray((prevArr) => [ ...prevArr, <rect x={rx} y={ry} height={height} width={width} /> ]); } };addRectangle en la última línea de mouseUp const mouseUp = () => { setMouseDown(false); addRectangle(); }; return ( <div className="App" ref={divRef}> <svg id="svg" ref={svgRef} onMouseDown={mouseDown} onMouseUp={mouseUp} onMouseMove={mouseMove} > {rectArray.map((rect) => rect)} </svg> </div> );