correct the implementation of useMount

This commit is contained in:
Pig Fang 2020-06-06 10:12:16 +08:00
parent a1ce50609f
commit c7b8cdab40
5 changed files with 126 additions and 114 deletions

View File

@ -1,16 +1,20 @@
import { useEffect, useMemo } from 'react'
import { useEffect, useRef } from 'react'
export default function useMount(selector: string): HTMLElement {
const container = useMemo(() => document.createElement('div'), [])
export default function useMount(selector: string): HTMLElement | null {
const container = useRef<HTMLDivElement | null>(null)
useEffect(() => {
const mount = document.querySelector(selector)!
mount.appendChild(container)
const div = document.createElement('div')
container.current = div
mount.appendChild(div)
return () => {
mount.removeChild(container)
mount.removeChild(div)
container.current = null
}
}, [])
return container
return container.current
}

View File

@ -238,87 +238,88 @@ const Show: React.FC = () => {
return (
<React.Fragment>
{createPortal(
<React.Suspense fallback={<ViewerSkeleton />}>
<Previewer
{...{
[texture.type === TextureType.Cape
? TextureType.Cape
: 'skin']: textureUrl,
}}
isAlex={texture.type === TextureType.Alex}
initPositionZ={60}
>
{currentUid === 0 ? (
<button
className="btn btn-outline-secondary"
title={t('skinlib.show.anonymous')}
disabled
>
{t('skinlib.addToCloset')}
</button>
) : (
<div className="d-flex justify-content-between align-items-center">
<div>
{liked && (
<button
className="btn btn-outline-success mr-2"
onClick={handleOpenModalApply}
>
{t('skinlib.apply')}
</button>
)}
{liked ? (
<button
className="btn btn-outline-primary mr-2"
onClick={handleRemoveItemClick}
>
{t('skinlib.removeFromCloset')}
</button>
) : (
<button
className="btn btn-outline-primary mr-2"
onClick={handleAddItemClick}
>
{t('skinlib.addToCloset')}
</button>
)}
{texture.type !== TextureType.Cape && (
<button
className="btn btn-outline-info mr-2"
onClick={handleSetAsAvatar}
>
{t('user.setAsAvatar')}
</button>
)}
{canBeDownloaded && (
<button
className="btn btn-outline-info mr-2"
onClick={handleDownloadClick}
>
{t('skinlib.show.download')}
</button>
)}
<button
className="btn btn-outline-info mr-2"
onClick={handleReport}
>
{t('skinlib.report.title')}
</button>
</div>
<div
className={liked ? 'text-red' : 'text-gray'}
title={t('skinlib.show.likes')}
{container &&
createPortal(
<React.Suspense fallback={<ViewerSkeleton />}>
<Previewer
{...{
[texture.type === TextureType.Cape
? TextureType.Cape
: 'skin']: textureUrl,
}}
isAlex={texture.type === TextureType.Alex}
initPositionZ={60}
>
{currentUid === 0 ? (
<button
className="btn btn-outline-secondary"
title={t('skinlib.show.anonymous')}
disabled
>
<i className="fas fa-heart mr-1" />
<span>{texture.likes}</span>
{t('skinlib.addToCloset')}
</button>
) : (
<div className="d-flex justify-content-between align-items-center">
<div>
{liked && (
<button
className="btn btn-outline-success mr-2"
onClick={handleOpenModalApply}
>
{t('skinlib.apply')}
</button>
)}
{liked ? (
<button
className="btn btn-outline-primary mr-2"
onClick={handleRemoveItemClick}
>
{t('skinlib.removeFromCloset')}
</button>
) : (
<button
className="btn btn-outline-primary mr-2"
onClick={handleAddItemClick}
>
{t('skinlib.addToCloset')}
</button>
)}
{texture.type !== TextureType.Cape && (
<button
className="btn btn-outline-info mr-2"
onClick={handleSetAsAvatar}
>
{t('user.setAsAvatar')}
</button>
)}
{canBeDownloaded && (
<button
className="btn btn-outline-info mr-2"
onClick={handleDownloadClick}
>
{t('skinlib.show.download')}
</button>
)}
<button
className="btn btn-outline-info mr-2"
onClick={handleReport}
>
{t('skinlib.report.title')}
</button>
</div>
<div
className={liked ? 'text-red' : 'text-gray'}
title={t('skinlib.show.likes')}
>
<i className="fas fa-heart mr-1" />
<span>{texture.likes}</span>
</div>
</div>
</div>
)}
</Previewer>
</React.Suspense>,
container,
)}
)}
</Previewer>
</React.Suspense>,
container,
)}
<div className="card card-primary">
<div className="card-header">
<h3 className="card-title">{t('skinlib.show.detail')}</h3>

View File

@ -233,16 +233,17 @@ const Upload: React.FC = () => {
)}
</div>
</div>
{ReactDOM.createPortal(
<React.Suspense fallback={<ViewerSkeleton />}>
<Previewer
skin={type !== TextureType.Cape ? texture : undefined}
cape={type === TextureType.Cape ? texture : undefined}
isAlex={type === TextureType.Alex}
/>
</React.Suspense>,
container,
)}
{container &&
ReactDOM.createPortal(
<React.Suspense fallback={<ViewerSkeleton />}>
<Previewer
skin={type !== TextureType.Cape ? texture : undefined}
cape={type === TextureType.Cape ? texture : undefined}
isAlex={type === TextureType.Alex}
/>
</React.Suspense>,
container,
)}
</>
)
}

View File

@ -17,13 +17,16 @@ const Previewer: React.FC<Props> = (props) => {
const skin = props.skin ? `${blessing.base_url}/textures/${props.skin}` : ''
const cape = props.cape ? `${blessing.base_url}/textures/${props.cape}` : ''
return ReactDOM.createPortal(
<React.Suspense fallback={<ViewerSkeleton />}>
<Viewer skin={skin} cape={cape} isAlex={props.isAlex} showIndicator>
{props.children}
</Viewer>
</React.Suspense>,
container,
return (
container &&
ReactDOM.createPortal(
<React.Suspense fallback={<ViewerSkeleton />}>
<Viewer skin={skin} cape={cape} isAlex={props.isAlex} showIndicator>
{props.children}
</Viewer>
</React.Suspense>,
container,
)
)
}

View File

@ -28,19 +28,22 @@ const Previewer: React.FC<Props> = (props) => {
const { skin, cape, isAlex } = props
return ReactDOM.createPortal(
is3d ? (
<React.Suspense fallback={<ViewerSkeleton />}>
<Viewer3d skin={skin} cape={cape} isAlex={isAlex}>
return (
container &&
ReactDOM.createPortal(
is3d ? (
<React.Suspense fallback={<ViewerSkeleton />}>
<Viewer3d skin={skin} cape={cape} isAlex={isAlex}>
{switcher}
</Viewer3d>
</React.Suspense>
) : (
<Viewer2d skin={skin} cape={cape}>
{switcher}
</Viewer3d>
</React.Suspense>
) : (
<Viewer2d skin={skin} cape={cape}>
{switcher}
</Viewer2d>
),
container,
</Viewer2d>
),
container,
)
)
}