Búsqueda de sitios web

reactjs - ¿Cómo agregar un listener de eventos al elemento div accedido con ref usando React y TypeScript?


quiero añadir un listener de eventos al elemento div usando ref.

Agrego ref div_ref al div Wrapper y accedo a ese div_ref en el método enableDragEventListeners para agregar event listeners a ese div al montar el componente.

A continuación está mi código,

const SomeComponent: React.FC<any> = props => {
    const div_ref  = React.useRef(null);
    React.useEffect(() => {
        const enableDragEventListeners = () => {
            const div = dropRef.current;
            if (div) {
                div.addEventListener('dragenter', handleDragIn); // get error here
                div.addEventListener('dragleave', handleDragOut); //error here
                div.addEventListener('dragover', handleDrag);//error here
                div.addEventListener('drop', handleDrop);//error here
            } 
        };
        enableDragEventListeners();
    }, []);

    return (
        <Wrapper ref={div_ref}>
           {dragging && <Overlay>{props.children}</Overlay>}
        </Wrapper>
    );
}

Pero recibo el error de que la propiedad addEventListener no existe en el tipo 'never'. ¿Alguien podría ayudarme a solucionar esto? Gracias.

Editar: El código completo se ve así... estoy implementando un componente de arrastrar y soltar, así que envolver esto alrededor de un componente que quiera usarlo podrá arrastrar y soltar archivos en él.

const DragAndDrop: React.FC<any> = props => {
    const dropRef = useRef(null);
    const [dragging, setDragging] = useState(false);
    const [dragCounter, setDragCounter] = useState(0);
    React.useEffect(() => {
        // componentDidMount()
        const handleDrag = (e: any) => {
            if (!props.loading) {
                e.preventDefault();
                e.stopPropagation();
            }
        };

        const handleDragIn = (e: any) => {
            if (!props.loading) {
                e.preventDefault();
                e.stopPropagation();
                setDragCounter((prev: number) => prev + 1);
                if (e.dataTransfer.files) {
                    setDragging(true);
                }
            } 
        };

        const handleDragOut = (e: any) => {
            if (!props.loading) {
                e.preventDefault();
                e.stopPropagation();
                setDragCounter((prev: number) => prev - 1);
                if (dragCounter === 0) {
                    setDragging(false);
                }
            }
        };

        const handleDrop = (e: any) => {
            if (!props.loading) {
                e.preventDefault();
                e.stopPropagation();
                setDragging(false);
                if (e.dataTransfer.files && e.dataTransfer.files.length > 0){ 
                    props.handle_drop(e);
                    e.dataTransfer.clearData();
                   setDragCounter(0);
                }
            }
       };
       const enableDragEventListeners = () => {
           const div = dropRef && dropRef.current;
           if (div) {
               div.addEventListener('dragenter', handleDragIn);
               div.addEventListener('dragleave', handleDragOut);
               div.addEventListener('dragover', handleDrag);
               div.addEventListener('drop', handleDrop);
           }
       };
       const disableDragEventListeners = () => {
           const div = dropRef && dropRef.current;
           div.removeEventListener('dragenter', handleDragIn);
           div.removeEventListener('dragleave', handleDragOut);
           div.removeEventListener('dragover', handleDrag);
           div.removeEventListener('drop', handleDrop);
       };
       setDragCounter(0);
       enableDragEventListeners();
       return () => {
           // componentWillUnmount()
           disableDragEventListeners();
       };
   }, [dragCounter, props]);

   return (
       <wrapper ref={dropRef}>
           {dragging && <Overlay>{props.children}</Overlay>}
       </Wrapper>
   ); 
};

const DropZone = styled.div``;

export default DragAndDrop;

Respuesta #1

Problema :

const div_ref = React.useRef(null); // < --- due to null it type of div_ref becomes null 

Solución :

const div_ref = React.useRef<any>(null); // <--- Provide type any
// OR
const div_ref = React.useRef<TYPE_OF_WRAPPER>(null); // <--- Provide the type of ref element

Demostración de ejemplo : (Con el elemento div, puedes eliminar el tipo y marcar, lanzará el mismo error)

NOTA: Y creo que dropRef.current; debería ser div_ref.current;

Respuesta #2

No estoy seguro de por qué estás agregando manualmente esos listeners de eventos a través de la referencia del componente, pero dado que estás agregando esos listeners de eventos cuando el componente se monta, puedes enlazar esos métodos a los eventos sintéticos.

<Wrapper 
  ref={div_ref}
  onDragEnter={handleDragIn}
  onDragLeave={handleDragOut}
  onDragover={handleDrag};
  onDrop={handleDrop}
>

Artículos relacionados