You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Closes#1
* Update README with render callbacks
Includes src, srcSet and alt for LazyImage, and a note on how they
keep things consistent and DRY.
* Run prettier on README
* Add alt, src, srcSet to render callbacks
* Fixes with TS checks
* Update stories with new callbacks
* Fix alt in story
Note that while you can set the rendered components to be anything you want, you most likely want to use the same `src`, `srcSet` and `alt` attributes in an `<img>` eventually.
118
+
To keep this consistent, and reduce repetition, the render callbacks pass those attributes back to you.
119
+
124
120
[You can play around with this library on Codesandbox](https://codesandbox.io/s/jnn9wjkj1w).
125
121
126
122
Additionally, make sure you understand [how to polyfill IntersectionObserver](#polyfill-intersectionobserver) and [strategies for when JS is not available](#fallback-without-javascript).
@@ -140,30 +136,34 @@ Thus, whether you want to display a simple `<img>`, your own `<Image>`, or even
140
136
```jsx
141
137
<LazyImage
142
138
src="/img/porto_buildings_large.jpg"
143
-
// This is rendered first
139
+
alt="Buildings with tiled exteriors, lit by the sunset."
140
+
141
+
// This is rendered first, notice how the src is different
144
142
placeholder={
145
-
() =>
146
-
<img src="/img/porto_buildings_lowres.jpg" alt="Buildings with tiled exteriors, lit by the sunset."/>
actual={({ src, alt }) =><img src={src} alt={alt} />}
303
293
/>
304
294
```
305
295
@@ -350,14 +340,15 @@ I also think that using the server method, albeit safe, would be messy with some
350
340
351
341
**Silver lining:**
352
342
353
-
There is generally no case where `<noscript>` will be rendered by client-side react.
343
+
There is generally no case where `<noscript>` will be rendered by client-side react.
354
344
This means that, if you are in charge of server-rendering and you trust your bundling setup, then you can have this fallback!
355
345
Look at [`src/fallbackUtils.tsx`](./src/fallbackUtils.tsx) for a function that can work.
356
346
You would probably do something like this:
357
347
358
348
```jsx
359
349
<LazyImage
360
350
src="actualImgSrc"
351
+
alt="alt description here"
361
352
placeholder={//the usual}
362
353
actual={//the usual}
363
354
/>
@@ -414,33 +405,42 @@ Read the notes section either on Storybook or the story source if you are wonder
414
405
[The starter on Codesandbox](https://codesandbox.io/s/jnn9wjkj1w) has a good basis for two popular presentational patterns.
415
406
In particular, it shows intrinsic placeholders and fading in the actual image.
416
407
408
+
You might be thinking that this library has a lot of wiring exposed.
409
+
This is very much intended.
410
+
If this library were to provide presentational patterns out of the box, then it would lead to many issues and PRs about what ultimately is opinion.
411
+
Being inclined to fork a library just to add a prop is not a nice situation to be in, compared to writing one abstracted component for your specific use case.
412
+
The behaviour and loading patterns are configurable, because those are what this library is about.
413
+
The presentation can be derived from those plus, crucially, any specific needs your application has.
414
+
417
415
## API Reference
418
416
419
417
**`<LazyImage />`** accepts the following props:
420
418
421
-
| Name | Type | Default | Required | Description |
| **src** | String | | true | The source of the image to load |
422
+
| **alt** | String | | false | The alt text description of the image you are loading |
423
+
| **srcSet** | String | | false | If your images use srcset, you can pass the `srcSet` prop to provide that information for preloading. |
424
+
| **actual** | Function (render callback) of type ({src, alt, srcSet}) => React.ReactNode | | true | Component to display once image has loaded |
425
+
| **placeholder** | Function (render callback) of type ({alt}) => React.ReactNode | undefined | false | Component to display while no request for the actual image has been made |
426
+
| **loading** | Function (render callback) of type () => React.ReactNode | placeholder | false | Component to display while the image is loading |
427
+
| **error** | Function (render callback) of type () => React.ReactNode | actual (broken image) | false | Component to display if the image loading has failed (render prop) |
428
+
| **loadEagerly** | Boolean | false | false | Whether to skip checking for viewport and always show the 'actual' component |
429
+
| **observerProps** | {threshold: number, rootMargin: string} | {threshold: 0.01, rootMargin: "50px 0px"} | false | Subset of props for the IntersectionObserver |
433
430
434
431
**`<LazyImageFull />`** accepts the following props:
435
432
436
-
| Name | Type | Default | Required | Description |
| **src** | String | | true | The source of the image to load |
439
-
| **srcSet** | String | | false | If your images use srcset, you can pass the `srcSet` prop to provide that information for preloading. |
440
-
| **loadEagerly** | Boolean | false | false | Whether to skip checking for viewport and always show the 'actual' component |
441
-
| **observerProps** | {threshold: number, rootMargin: string} | {threshold: 0.01, rootMargin: "50px 0px"} | false | Subset of props for the IntersectionObserver |
442
-
| **render** | Function of type ({src, srcSet, imageState}) => React.ReactNode | | true (or `children`) | Function to call that renders based on the props and state provided to it by LazyImageFull |
443
-
| **children** | Function of type ({src, srcSet, imageState}) => React.ReactNode | | true (or `render`) | Function to call that renders based on the props and state provided to it by LazyImageFull |
433
+
| Name | Type | Default | Required | Description |
| **src** | String | | true | The source of the image to load |
436
+
| **alt** | String | | false | The alt text description of the image you are loading |
437
+
| **srcSet** | String | | false | If your images use srcset, you can pass the `srcSet` prop to provide that information for preloading. |
438
+
| **loadEagerly** | Boolean | false | false | Whether to skip checking for viewport and always show the 'actual' component |
439
+
| **observerProps** | {threshold: number, rootMargin: string} | {threshold: 0.01, rootMargin: "50px 0px"} | false | Subset of props for the IntersectionObserver |
440
+
| **render** | Function of type ({src, alt, srcSet, imageState}) => React.ReactNode | | true (or `children`) | Function to call that renders based on the props and state provided to it by LazyImageFull |
441
+
| **children** | Function of type ({src, alt, srcSet, imageState}) => React.ReactNode | | true (or `render`) | Function to call that renders based on the props and state provided to it by LazyImageFull |
442
+
443
+
[You can consult Typescript types in the code](./src/LazyImage.tsx) for more context.
444
444
445
445
## Feedback
446
446
@@ -455,18 +455,19 @@ See [`ROADMAP.md`](./ROADMAP.md) for information and ideas about where the proje
455
455
I would love to have contributions on this! Are there more patterns that we can expose and simplify? Is something not clear? See `CONTRIBUTING.md` for details.
456
456
457
457
## Thanks and Inspiration
458
+
458
459
Here are some resources whose ideas resonate with me and have informed this library.
459
460
460
-
- Jeremy Wagner's writing on [Lazy Loading Images and Video](https://developers.google.com/web/fundamentals/performance/lazy-loading-guidance/images-and-video/) is a good reference for the problem and solutions space.
461
+
* Jeremy Wagner's writing on [Lazy Loading Images and Video](https://developers.google.com/web/fundamentals/performance/lazy-loading-guidance/images-and-video/) is a good reference for the problem and solutions space.
461
462
462
-
- The library backing this one, [react-intersection-observer](https://github.com/thebuilder/react-intersection-observer).
463
-
Further thanks for demonstrating Storybook as documentation for lazy-loading.
463
+
* The library backing this one, [react-intersection-observer](https://github.com/thebuilder/react-intersection-observer).
464
+
Further thanks for demonstrating Storybook as documentation for lazy-loading.
464
465
465
-
- [José M. Pérez has a good resource on lazy loading](https://jmperezperez.com/high-performance-lazy-loading/)
466
+
* [José M. Pérez has a good resource on lazy loading](https://jmperezperez.com/high-performance-lazy-loading/)
466
467
467
-
- [Paul Lewis' implementation of lazy image loading](https://github.com/GoogleChromeLabs/sample-media-pwa/blob/master/src/client/scripts/helpers/lazy-load-images.js) has the concept of pre-loading images before swapping.
468
+
* [Paul Lewis' implementation of lazy image loading](https://github.com/GoogleChromeLabs/sample-media-pwa/blob/master/src/client/scripts/helpers/lazy-load-images.js) has the concept of pre-loading images before swapping.
468
469
469
-
- [Dave Rupert has a good guide on intrinsic image placeholders](https://daverupert.com/2015/12/intrinsic-placeholders-with-picture/)
470
+
* [Dave Rupert has a good guide on intrinsic image placeholders](https://daverupert.com/2015/12/intrinsic-placeholders-with-picture/)
0 commit comments