Skip to content

Commit 76a6557

Browse files
author
fpapado
committed
Split logic into LazyImageFull
LazyImageFull allows for more fine-grained rendering based on the state. This is particularly useful for css transitions and when re-rendering is undesirable. LazyImage has been reimplemented on top of this.
1 parent 51fa369 commit 76a6557

File tree

7 files changed

+14064
-158
lines changed

7 files changed

+14064
-158
lines changed

README.md

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ Additionally, make sure you understand [how to polyfill IntersectionObserver](#p
118118
From then on:
119119

120120
* If you want to learn more about the API and the problem space, read the rest of this section.
121-
* If you want to list the props, see the [API reference](#api-reference)
121+
* If you need more fine-grained rendering, [read about `LazyImageFull`](#more-control-with-lazyimagefull).
122+
* If you want to list the props, see the [API reference](#api-reference).
122123

123124
### Customising what is displayed
124125

@@ -160,6 +161,39 @@ Thus, whether you want to display a simple `<img>`, your own `<Image>`, or even
160161
161162
These props are there to instruct the component what to render in those places, and they take some useful information (in this case, a className) from the LazyImage.
162163
164+
### More control with LazyImageFull
165+
166+
`LazyImage` should work for most cases, but you might need more fine-grained rendering.
167+
One use case would be doing animations with CSS transitions, where re-rendering the component (which `LazyImage` does) would not be sufficient.
168+
In those cases, consider `LazyImageFull`:
169+
170+
```jsx
171+
import {LazyImageFull, ImageState} from 'react-lazy-images';
172+
173+
// Function as child
174+
<LazyImageFull>
175+
{({src, srcSet, imageState}) =>
176+
<img src={imageState === ImageState.LoadSuccess ? 'https://fillmurray.com/g/600/400 : 'https://fillmurray.com/g/30/20'} style={{opacity: ImageState.LoadSuccess ? '1' : '0.5'}} />
177+
}
178+
</LazyImageFull>
179+
180+
// render prop
181+
<LazyImageFull
182+
render={({src, srcSet, imageState}) =>
183+
<img src={imageState === ImageState.LoadSuccess ? 'https://fillmurray.com/g/600/400 : 'https://fillmurray.com/g/30/20'} style={{opacity: ImageState.LoadSuccess ? '1' : '0.5'}} />
184+
} />
185+
```
186+
187+
This component takes a function as a child, which accepts `{src, srcSet, imageState}`.
188+
The various image states are imported as `{ImageState}`, and you can conditionally render based on them.
189+
You can also pass this function as a `render` prop.
190+
191+
This technique can give you more fine-grained rendering if needed, but can potentially be more verbose.
192+
Any of the presentational patterns presented that are possible with `LazyImage` are also possible with `LazyImageFull`.
193+
(The opposite is not necessarily true, or at least has more duplication).
194+
195+
In fact, if you check [`src/LazyImage.tsx`](./src/LazyImage.tsx), you will see that `LazyImage` is implemented in terms of `LazyImageFull`!
196+
163197
### Load before swap
164198
165199
A common optimisation to the loading strategy is to preload the image before swapping it for the placeholder.
@@ -355,12 +389,23 @@ In particular, it shows intrinsic placeholders and fading in the actual image.
355389
| **actual** | Function (render prop) | | true | Component to display once image has loaded |
356390
| **placeholder** | Function (render prop) | undefined | false | Component to display while no request for the actual image has been made |
357391
| **loading** | Function (render prop) | placeholder | false | Component to display while the image is loading |
358-
| **error** | Function | actual (broken image) | false | Component to display if the image loading has failed (render prop) |
392+
| **error** | Function (render prop) | actual (broken image) | false | Component to display if the image loading has failed (render prop) |
359393
| **loadEagerly** | Boolean | false | false | Whether to skip checking for viewport and always show the 'actual' component |
360394
| **observerProps** | {threshold: number, rootMargin: string} | {threshold: 0.01, rootMargin: "50px 0px"} | false | Subset of props for the IntersectionObserver |
361395
362396
[You can consult Typescript types in the code](./src/LazyImage.tsx) as a more exact definition.
363397
398+
**`<LazyImageFull />`** accepts the following props:
399+
400+
| Name | Type | Default | Required | Description |
401+
| ----------------- | --------------------------------------------------------------- | ----------------------------------------- | -------------------- | ----------------------------------------------------------------------------------------------------- |
402+
| **src** | String | | true | The source of the image to load |
403+
| **srcSet** | String | | false | If your images use srcset, you can pass the `srcSet` prop to provide that information for preloading. |
404+
| **loadEagerly** | Boolean | false | false | Whether to skip checking for viewport and always show the 'actual' component |
405+
| **observerProps** | {threshold: number, rootMargin: string} | {threshold: 0.01, rootMargin: "50px 0px"} | false | Subset of props for the IntersectionObserver |
406+
| **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 |
407+
| **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 |
408+
364409
## Feedback
365410
366411
I have some specific questions that I would like input on. If you want to go exploring, or have used the library and had gripes with it, then see [`FEEDBACK.md`](./FEEDBACK.md) and let's have a discussion!

0 commit comments

Comments
 (0)