React Image is an <img> tag
replacement and hook for React.js, supporting
fallback to alternate sources when loading an image fails.
React Image allows one or more images to be used as
fallback images in the event that the browser couldn’t load the previous
image. When using the component, you can specify any React element to be
used before an image is loaded (i.e. a spinner) or in the event that the
specified image(s) could not be loaded. When using the hook this can be
achieved by wrapping the component with <Suspense>
and specifying the fallback prop.
React Image uses the useImage hook
internally which encapsulates all the image loading logic. This hook
works with React Suspense by default and will suspend painting until the
image is downloaded and decoded by the browser.
react-image using npm:npm install react-image --save
<script src="https://unpkg.com/react-image/umd/index.js"></script>react-image has no external dependencies, aside for a
version of react and react-dom which support
hooks and @babel/runtime.
You can use the standalone component, documented below, or the
useImage hook.
The useImage hook allows for incorperating
react-image’s logic in any component. When using the hook,
the component can be wrapped in <Suspense> to keep it
from rendering until the image is ready. Specify the
fallback prop to show a spinner or any other component to
the user while the browser is loading. The hook will throw an error if
it failes to find any images. You can wrap your componenet with an Error
Boundry to catch this scenario and do/show something.
Example usage:
import React, {Suspense} from 'react'
import {useImage} from 'react-image'
function MyImageComponent() {
const {src} = useImage({
srcList: 'https://www.example.com/foo.jpg',
})
return <img src={src} />
}
export default function MyComponent() {
return (
<Suspense>
<MyImageComponent />
</Suspense>
)
}useImage API:srcList: a string or array of strings.
useImage will try loading these one at a time and returns
after the first one is successfully loaded
imgPromise: a promise that accepts a url and returns
a promise which resolves if the image is successfully loaded or rejects
if the image doesn’t load. You can inject an alternative implementation
for advanced custom behaviour such as logging errors or dealing with
servers that return an image with a 404 header
useSuspense: boolean. By default,
useImage will tell React to suspend rendering until an
image is downloaded. Suspense can be disabled by setting this to
false.
returns:
src: the resolved image addressisLoading: the currently loading status. Note: this is
never true when using Suspenseerror: any errors ecountered, if anyWhen possible, you should use the useImage hook. This
provides for greater flexability and provides support for React
Suspense.
Include react-image in your component:
import {Img} from 'react-image'and set a source for the image:
const myComponent = () => <Img src="https://www.example.com/foo.jpg" />will resolve to:
<img src="https://www.example.com/foo.jpg">If the image cannot be loaded, <img> will
not be rendered, preventing a “broken” image from showing.
When src is specified as an array,
react-image will attempt to load all the images specified
in the array, starting at the first and continuing until an image has
been successfully loaded.
const myComponent = () => (
<Img
src={['https://www.example.com/foo.jpg', 'https://www.example.com/bar.jpg']}
/>
)If an image has previously been attempted unsuccessfully,
react-image will not retry loading it again until the page
is reloaded.
const myComponent = () => (
<Img
src={['https://www.example.com/foo.jpg', 'https://www.example.com/bar.jpg']}
loader={/*any valid react element */}
/>
)If an image was previously loaded successfully (since the last time the page was loaded), the loader will not be shown and the image will be rendered immediately instead.
const myComponent = () => (
<Img
src={['https://www.example.com/foo.jpg', 'https://www.example.com/bar.jpg']}
unloader={/*any valid react element */}
/>
)The following options only apply to the <Img>
component, not to the useImage hook. When using the hook
you can inject a custom image resolver with custom behaviour as
required.
By default and when supported by the browser,
react-image uses Image.decode()
to decode the image and only render it when it’s fully ready to be
painted. While this doesn’t matter much for vector images (such as
svg’s) which are rendered immediately, decoding the image before
painting prevents the browser from hanging or flashing while the image
is decoded. If this behaviour is undesirable, it can be disabled by
setting the decode prop to false:
const myComponent = () => (
<Img src={'https://www.example.com/foo.jpg'} decode={false} />
)When loading images from another domain with a CORS
policy, you may find you need to use the crossorigin
attribute. For example:
const myComponent = () => (
<Img src={'https://www.example.com/foo.jpg'} crossorigin="anonymous" />
)A wrapper element container can be used to facilitate
higher level operations which are beyond the scope of this project.
container takes a single property, children
which is whatever is passed in by React Image (i.e. the
final <img> or the loaders).
For example, to animate the display of the image (and animate out the loader) a wrapper can be set:
<Img
src={'https://www.example.com/foo.jpg'}
container={(children) => {
return <div className="foo">{children}</div>
}}
/>The <img> will now be contained by the
div with class foo which can be targeted via
css. A crude example of a transition using ReactCSSTransitionReplace
can be found
here. Error reporting (i.e. logging images that loaded ok or failed
to load) can be accomplished with container, too. A sample
implementation can be found
here.
By default, the loader and unloader components will also be wrapped
by the container component. These can be set independently
by passing a container via loaderContainer or
unloaderContainer. To disable the loader or unloader from
being wrapped, pass a noop to loaderContainer or
unloaderContainer (like
unloaderContainer={img => img}).
By definition, React Image will try loading images
right away. This may be undesirable in some situations, such as when the
page has many images. As with any react element, rendering can be
delayed until the image is actually visible in the viewport using
popular libraries such as react-visibility-sensor.
Here is a quick sample (psudocode/untested!):
import {Img} from 'react-image'
import VisibilitySensor from 'react-visibility-sensor'
const myComponent = () =>
<VisibilitySensor>
<Img src='https://www.example.com/foo.jpg'>
</VisibilitySensor>Note: it is not nesesary to use React Image to
prevent loading of images past “the fold” (i.e. not currently visable on
in the window). Instead just use the native HTML
<img> element and the loading="lazy"
prop. See more here.
see above
react-image is available under the MIT License