Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix types for lazy image component #17984

Merged
merged 1 commit into from Oct 18, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
110 changes: 51 additions & 59 deletions packages/next/client/image.tsx
@@ -1,28 +1,30 @@
import React, { ReactElement, useEffect } from 'react'
import React, { ReactElement, useEffect, useRef } from 'react'
import Head from '../next-server/lib/head'

const loaders: { [key: string]: (props: LoaderProps) => string } = {
imgix: imgixLoader,
cloudinary: cloudinaryLoader,
default: defaultLoader,
}

type ImageData = {
sizes?: number[]
hosts: {
[key: string]: {
path: string
loader: string
}
}
breakpoints?: number[]
}

type ImageProps = Omit<JSX.IntrinsicElements['img'], 'src' | 'sizes'> & {
type ImageProps = Omit<
JSX.IntrinsicElements['img'],
'src' | 'srcSet' | 'ref'
> & {
src: string
host?: string
sizes?: string
priority?: boolean
lazy: boolean
className: string
lazy?: boolean
unoptimized?: boolean
}

Expand Down Expand Up @@ -143,10 +145,12 @@ export default function Image({
sizes,
unoptimized = false,
priority = false,
lazy,
lazy = false,
className,
...rest
}: ImageProps) {
const thisEl = useRef<HTMLImageElement>(null)

// Sanity Checks:
if (process.env.NODE_ENV !== 'production') {
if (unoptimized && host) {
Expand Down Expand Up @@ -178,46 +182,54 @@ export default function Image({
src = src.slice(1)
}

let thisEl: any

useEffect(() => {
if (lazy) {
const target = thisEl.current

if (target && lazy) {
const observer = getObserver()

if (observer) {
observer.observe(thisEl)
observer.observe(target)

return () => {
observer.unobserve(thisEl)
observer.unobserve(target)
}
}
}
}, [thisEl, lazy])

// Generate attribute values
const imgSrc = computeSrc(src, host, unoptimized)
let imgSrcset = null
if (!unoptimized) {
imgSrcset = generateSrcSet({
src,
host: host,
widths: breakpoints,
})
}
const imgSrcSet = !unoptimized
? generateSrcSet({
src,
host: host,
widths: breakpoints,
})
: undefined

const imgAttributes: {
src?: string
srcSet?: string
'data-src'?: string
'data-srcset'?: string
} = {}
let imgAttributes:
| {
src: string
srcSet?: string
}
| {
'data-src': string
'data-srcset'?: string
}
if (!lazy) {
imgAttributes.src = imgSrc
if (imgSrcset) {
imgAttributes.srcSet = imgSrcset
imgAttributes = {
src: imgSrc,
}
if (imgSrcSet) {
imgAttributes.srcSet = imgSrcSet
}
} else {
imgAttributes['data-src'] = imgSrc
if (imgSrcset) {
imgAttributes['data-srcset'] = imgSrcset
imgAttributes = {
'data-src': imgSrc,
}
if (imgSrcSet) {
imgAttributes['data-srcset'] = imgSrcSet
}
className = className ? className + ' __lazy' : '__lazy'
}
Expand All @@ -226,32 +238,6 @@ export default function Image({
// it's too late for preloads
const shouldPreload = priority && typeof window === 'undefined'

let imgElement
if (className) {
imgElement = (
<img
{...rest}
ref={(el) => {
thisEl = el
}}
{...imgAttributes}
className={className}
sizes={sizes}
/>
)
} else {
imgElement = (
<img
ref={(el) => {
thisEl = el
}}
{...rest}
{...imgAttributes}
sizes={sizes}
/>
)
}

return (
<div>
{shouldPreload
Expand All @@ -263,7 +249,13 @@ export default function Image({
sizes,
})
: ''}
{imgElement}
<img
{...rest}
{...imgAttributes}
className={className}
sizes={sizes}
ref={thisEl}
/>
</div>
)
}
Expand Down