Estoy usando react-dnd (arrastrar y soltar) para colocar elementos en un div que actúa como un lienzo para contener los elementos. Como tenía problemas para que dnd no actualizara la referencia del estado del lienzo, tuve que usar un gancho useRef para actualizarlo manualmente.
const [canvas, setCanvas] = useState([]) const canvasRef = useRef(null); //Function to update the referrence const _setCanvas = (Canvas) => { canvasRef.current = Canvas; setCanvas(Canvas); }; const [{ isOver }, drop] = useDrop(() => ({ accept: "formElement", drop: (item) => { addElementToCanvas(item.id, generateUUID()); }, collect: (monitor) => ({ isOver: !!monitor.isOver(), }), })); //Function to add element on to the canvas const addElementToCanvas = (id, uuid) => { const formElement = formElements.find((element) => id === element.id); //Add up the necessary details required for the element formElement.question = "Type your question here"; if (!formElement) { return; } if (canvasRef.current === null) { canvasRef.current = []; } const formAreaElements = [...canvasRef.current, { ...formElement, uuid: uuid }]; _setCanvas(formAreaElements); setfilled(true); }; const removeElementfromCanvas = (formElement) => { const updatedForm = canvas.filter((element) => element.uuid != formElement.uuid) _setCanvas(updatedForm); };Agregar elementos al lienzo funciona bien. Sin embargo, al eliminar un elemento en particular por su uuid, el estado se actualiza con el resto de los elementos. Pero en el DOM, se elimina el último elemento que se agregó, y no el que ya se eliminó del estado.
<div className="bg-gray-800 w-full h-screen z-1 overflow-y-auto text-white " ref={drop} > {filled && canvasRef.current.map((element, idx) => { return ( <li key={idx} className="mt-8 cursor-default w-full "> <FormElementHolder questionNo={idx + 1} element={element} removeElement={() => removeElementfromCanvas(element)} canvasRef={canvasRef.current} _setCanvas={_setCanvas} /> </li> ); })} </div>;¡Gracias por adelantado!
Su elemento ya tiene una identificación, es mejor usarla en su lugar.
En general, es una mala práctica usar índices como claves y, en este caso, está causando un error.
El índice cambia cuando elimina un elemento y, por lo tanto, la biblioteca dnd no puede recordar las referencias adecuadas.
Este artículo es excelente para consultar: https://dev.to/shiv1998/why-not-to-use-index-as-key-in-react-lists-practical-example-3e66
<div className="bg-gray-800 w-full h-screen z-1 overflow-y-auto text-white" ref={drop} > {filled && canvasRef.current.map((element, idx) => { return ( <li key={element.id} className="mt-8 cursor-default w-full "> <FormElementHolder questionNo={idx + 1} element={element} removeElement={() => removeElementfromCanvas(element)} canvasRef={canvasRef.current} _setCanvas={_setCanvas} /> </li> ); })} ;No puede usar índices de manera confiable como claves cuando modifica la matriz de esa manera. Detalles en este artículo enlazado desde la documentación de React . El problema es que al volver a renderizar, React piensa que puede mantener/reutilizar el elemento DOM para lo anterior en ese índice cuando le das algo nuevo con ese mismo índice como su clave.
Parece que tiene una id en los elementos, así que use la id como clave.