Estoy usando una versión bastante estricta de TS y ESLint.
Extraje este portal de los documentos aquí: https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/portals/
Modifiqué el código a lo siguiente:
import React, { useEffect, useRef, ReactNode } from 'react'
import { createPortal } from 'react-dom'
interface Props {
children?: ReactNode
portalId: string
}
export const Portal: React.FC<Props> = ({ children, portalId }) => {
const el = useRef(document.createElement('div'))
useEffect(() => {
const portalRoot = document.querySelector(`#${portalId}`) as HTMLElement
const current = el.current
portalRoot.appendChild(current)
return () => void portalRoot?.removeChild(current) // error thrown here?
}, [portalId])
return createPortal(children, el.current)
}
Error a continuación:
Esperaba 'indefinido' y en su lugar vio 'vacío'
Cuando elimino el void (no puedo usar undefined , de lo contrario, el resto del código es inalcanzable), como tal:
import React, { useEffect, useRef, ReactNode } from 'react'
import { createPortal } from 'react-dom'
interface Props {
children?: ReactNode
portalId: string
}
export const Portal: React.FC<Props> = ({ children, portalId }) => {
const el = useRef(document.createElement('div'))
useEffect(() => {
const portalRoot = document.querySelector(`#${portalId}`) as HTMLElement
const current = el.current
portalRoot.appendChild(current)
return () => portalRoot?.removeChild(current) // how to fix?
}, [portalId])
return createPortal(children, el.current)
}
Esto da como resultado otro error:
Argument of type '() => () => HTMLDivElement' is not assignable to parameter of type 'EffectCallback'.
Type '() => HTMLDivElement' is not assignable to type 'void | Destructor'.
Type '() => HTMLDivElement' is not assignable to type 'Destructor'.
Type 'HTMLDivElement' is not assignable to type 'void | { [UNDEFINED_VOID_ONLY]: never; }'
¿Como arreglar?
Simplemente significa que el "Destructor" (es decir, la función de limpieza que devuelve el useEffect ) no debería devolver nada.
Pero dado que usa una forma abreviada de función de flecha, su resultado se devuelve automáticamente. Simplemente envuélvalo con llaves, por ejemplo, para evitar el retorno automático:
return () => {
portalRoot?.removeChild(current)
}