mirror of
https://github.com/status-im/react-native-fast-image.git
synced 2025-02-22 19:28:32 +00:00
chore: convert examples to hooks (#830)
This commit is contained in:
parent
291876b6cd
commit
5946d3321e
@ -3,5 +3,6 @@ module.exports = {
|
||||
extends: '@react-native-community',
|
||||
rules: {
|
||||
semi: ['error', 'never'],
|
||||
'react-native/no-inline-styles': 'off',
|
||||
},
|
||||
}
|
||||
|
@ -10,5 +10,5 @@ import App from '../src'
|
||||
import renderer from 'react-test-renderer'
|
||||
|
||||
it('renders correctly', () => {
|
||||
renderer.create(<App />)
|
||||
renderer.create(<App />)
|
||||
})
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React, { Component } from 'react'
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import withCacheBust from './withCacheBust'
|
||||
import SectionFlex from './SectionFlex'
|
||||
import FastImage, { FastImageProps } from 'react-native-fast-image'
|
||||
import Section from './Section'
|
||||
import FeatureText from './FeatureText'
|
||||
import { useCacheBust } from './useCacheBust'
|
||||
|
||||
const GIF_URL =
|
||||
'https://cdn-images-1.medium.com/max/1600/1*-CY5bU4OqiJRox7G00sftw.gif'
|
||||
@ -16,73 +16,60 @@ interface AutoSizingImageProps extends FastImageProps {
|
||||
style?: any
|
||||
}
|
||||
|
||||
interface AutoSizingImageState {
|
||||
height: number
|
||||
width: number
|
||||
}
|
||||
|
||||
class AutoSizingImage extends Component<
|
||||
AutoSizingImageProps,
|
||||
AutoSizingImageState
|
||||
> {
|
||||
state = {
|
||||
const AutoSizingImage = (props: AutoSizingImageProps) => {
|
||||
const [dimensions, setDimensions] = useState({
|
||||
height: 0,
|
||||
width: 0,
|
||||
}
|
||||
})
|
||||
|
||||
onLoad = (e: any) => {
|
||||
const {
|
||||
nativeEvent: { width, height },
|
||||
} = e
|
||||
this.setState({ width, height })
|
||||
if (this.props.onLoad) {
|
||||
this.props.onLoad(e)
|
||||
const propsOnLoad = props.onLoad
|
||||
const onLoad = useCallback(
|
||||
(e: any) => {
|
||||
const {
|
||||
nativeEvent: { width, height },
|
||||
} = e
|
||||
setDimensions({ width, height })
|
||||
if (propsOnLoad) {
|
||||
propsOnLoad(e)
|
||||
}
|
||||
},
|
||||
[propsOnLoad],
|
||||
)
|
||||
|
||||
const height = useMemo(() => {
|
||||
if (!dimensions.height) {
|
||||
return props.defaultHeight === undefined ? 300 : props.defaultHeight
|
||||
}
|
||||
}
|
||||
|
||||
getHeight = () => {
|
||||
if (!this.state.height) {
|
||||
return this.props.defaultHeight === undefined
|
||||
? 300
|
||||
: this.props.defaultHeight
|
||||
}
|
||||
const ratio = this.state.height / this.state.width
|
||||
const height = this.props.width * ratio
|
||||
return height
|
||||
}
|
||||
|
||||
render() {
|
||||
const height = this.getHeight()
|
||||
return (
|
||||
<FastImage
|
||||
{...this.props}
|
||||
onLoad={this.onLoad}
|
||||
style={[{ width: this.props.width, height }, this.props.style]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
const ratio = dimensions.height / dimensions.width
|
||||
return props.width * ratio
|
||||
}, [dimensions.height, dimensions.width, props.defaultHeight, props.width])
|
||||
return (
|
||||
<FastImage
|
||||
{...props}
|
||||
onLoad={onLoad}
|
||||
style={[{ width: props.width, height }, props.style]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
interface AutoSizeExampleProps {
|
||||
onPressReload: () => void
|
||||
bust: boolean
|
||||
export const AutoSizeExample = () => {
|
||||
const { bust, url } = useCacheBust(GIF_URL)
|
||||
return (
|
||||
<View>
|
||||
<Section>
|
||||
<FeatureText text="• AutoSize." />
|
||||
</Section>
|
||||
<SectionFlex onPress={bust}>
|
||||
<AutoSizingImage
|
||||
style={styles.image}
|
||||
width={200}
|
||||
source={{ uri: url }}
|
||||
/>
|
||||
</SectionFlex>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const AutoSizeExample = ({ onPressReload, bust }: AutoSizeExampleProps) => (
|
||||
<View>
|
||||
<Section>
|
||||
<FeatureText text="• AutoSize." />
|
||||
</Section>
|
||||
<SectionFlex onPress={onPressReload}>
|
||||
<AutoSizingImage
|
||||
style={styles.image}
|
||||
width={200}
|
||||
source={{ uri: GIF_URL + bust }}
|
||||
/>
|
||||
</SectionFlex>
|
||||
</View>
|
||||
)
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
image: {
|
||||
backgroundColor: '#ddd',
|
||||
@ -90,5 +77,3 @@ const styles = StyleSheet.create({
|
||||
flex: 0,
|
||||
},
|
||||
})
|
||||
|
||||
export default withCacheBust(AutoSizeExample)
|
||||
|
@ -1,43 +1,38 @@
|
||||
import React from 'react'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import withCacheBust from './withCacheBust'
|
||||
import SectionFlex from './SectionFlex'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import Section from './Section'
|
||||
import FeatureText from './FeatureText'
|
||||
import { useCacheBust } from './useCacheBust'
|
||||
|
||||
const IMAGE_URL = 'https://media.giphy.com/media/GEsoqZDGVoisw/giphy.gif'
|
||||
|
||||
interface BorderRadiusExampleProps {
|
||||
onPressReload: () => void
|
||||
bust: string
|
||||
export const BorderRadiusExample = () => {
|
||||
const { query, bust } = useCacheBust('')
|
||||
return (
|
||||
<View>
|
||||
<Section>
|
||||
<FeatureText text="• Border radius." />
|
||||
</Section>
|
||||
<SectionFlex onPress={bust}>
|
||||
<FastImage
|
||||
style={styles.imageSquare}
|
||||
source={{
|
||||
uri: IMAGE_URL + query,
|
||||
}}
|
||||
/>
|
||||
<FastImage
|
||||
style={styles.imageRectangular}
|
||||
source={{
|
||||
uri: IMAGE_URL + query,
|
||||
}}
|
||||
/>
|
||||
</SectionFlex>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const BorderRadiusExample = ({
|
||||
onPressReload,
|
||||
bust,
|
||||
}: BorderRadiusExampleProps) => (
|
||||
<View>
|
||||
<Section>
|
||||
<FeatureText text="• Border radius." />
|
||||
</Section>
|
||||
<SectionFlex onPress={onPressReload}>
|
||||
<FastImage
|
||||
style={styles.imageSquare}
|
||||
source={{
|
||||
uri: IMAGE_URL + bust,
|
||||
}}
|
||||
/>
|
||||
<FastImage
|
||||
style={styles.imageRectangular}
|
||||
source={{
|
||||
uri: IMAGE_URL + bust,
|
||||
}}
|
||||
/>
|
||||
</SectionFlex>
|
||||
</View>
|
||||
)
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
imageSquare: {
|
||||
borderRadius: 50,
|
||||
@ -64,5 +59,3 @@ const styles = StyleSheet.create({
|
||||
right: 0,
|
||||
},
|
||||
})
|
||||
|
||||
export default withCacheBust(BorderRadiusExample)
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import { Image } from 'react-native'
|
||||
import ImageGrid from './ImageGrid'
|
||||
import { ImageGrid } from './ImageGrid'
|
||||
|
||||
const DefaultImageGrid = () => <ImageGrid ImageComponent={Image} />
|
||||
|
||||
|
@ -1,17 +1,17 @@
|
||||
import React from 'react'
|
||||
import { ScrollView, StatusBar, StyleSheet, Text, View } from 'react-native'
|
||||
import Section from './Section'
|
||||
import PriorityExample from './PriorityExample'
|
||||
import GifExample from './GifExample'
|
||||
import BorderRadiusExample from './BorderRadiusExample'
|
||||
import FeatureText from './FeatureText'
|
||||
import ProgressExample from './ProgressExample'
|
||||
import PreloadExample from './PreloadExample'
|
||||
import ResizeModeExample from './ResizeModeExample'
|
||||
import TintColorExample from './TintColorExample'
|
||||
import LocalImagesExample from './LocalImagesExample'
|
||||
import StatusBarUnderlay, { STATUS_BAR_HEIGHT } from './StatusBarUnderlay'
|
||||
import AutoSizeExample from './AutoSizeExample'
|
||||
import { PriorityExample } from './PriorityExample'
|
||||
import { GifExample } from './GifExample'
|
||||
import { BorderRadiusExample } from './BorderRadiusExample'
|
||||
import { ProgressExample } from './ProgressExample'
|
||||
import { PreloadExample } from './PreloadExample'
|
||||
import { ResizeModeExample } from './ResizeModeExample'
|
||||
import { TintColorExample } from './TintColorExample'
|
||||
import { LocalImagesExample } from './LocalImagesExample'
|
||||
import { AutoSizeExample } from './AutoSizeExample'
|
||||
|
||||
const FastImageExample = () => (
|
||||
<View style={styles.container}>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import ImageGrid from './ImageGrid'
|
||||
import { ImageGrid } from './ImageGrid'
|
||||
|
||||
const FastImageGrid = () => <ImageGrid ImageComponent={FastImage} />
|
||||
|
||||
|
@ -1,30 +1,28 @@
|
||||
import React from 'react'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import withCacheBust from './withCacheBust'
|
||||
import SectionFlex from './SectionFlex'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import Section from './Section'
|
||||
import FeatureText from './FeatureText'
|
||||
import { useCacheBust } from './useCacheBust'
|
||||
|
||||
const GIF_URL =
|
||||
'https://cdn-images-1.medium.com/max/1600/1*-CY5bU4OqiJRox7G00sftw.gif'
|
||||
|
||||
interface GifExampleProps {
|
||||
onPressReload: () => void
|
||||
bust: boolean
|
||||
export const GifExample = () => {
|
||||
const { url, bust } = useCacheBust(GIF_URL)
|
||||
return (
|
||||
<View>
|
||||
<Section>
|
||||
<FeatureText text="• GIF support." />
|
||||
</Section>
|
||||
<SectionFlex onPress={bust}>
|
||||
<FastImage style={styles.image} source={{ uri: url }} />
|
||||
</SectionFlex>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const GifExample = ({ onPressReload, bust }: GifExampleProps) => (
|
||||
<View>
|
||||
<Section>
|
||||
<FeatureText text="• GIF support." />
|
||||
</Section>
|
||||
<SectionFlex onPress={onPressReload}>
|
||||
<FastImage style={styles.image} source={{ uri: GIF_URL + bust }} />
|
||||
</SectionFlex>
|
||||
</View>
|
||||
)
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
image: {
|
||||
backgroundColor: '#ddd',
|
||||
@ -34,5 +32,3 @@ const styles = StyleSheet.create({
|
||||
flex: 0,
|
||||
},
|
||||
})
|
||||
|
||||
export default withCacheBust(GifExample)
|
||||
|
@ -1,144 +1,137 @@
|
||||
import React, { Component } from 'react'
|
||||
import {
|
||||
FlatList,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
LayoutChangeEvent,
|
||||
} from 'react-native'
|
||||
import React, { memo, useCallback, useEffect, useState } from 'react'
|
||||
import { FlatList, Text, View, LayoutChangeEvent } from 'react-native'
|
||||
import StatusBarUnderlay, { STATUS_BAR_HEIGHT } from './StatusBarUnderlay'
|
||||
|
||||
const getImageUrl = (id: string, width: number, height: number) =>
|
||||
`https://unsplash.it/${width}/${height}?image=${id}`
|
||||
|
||||
interface ImageGridProps {
|
||||
const MARGIN = 2
|
||||
|
||||
export interface ImageGridItemProps {
|
||||
id: string
|
||||
ImageComponent: any
|
||||
}
|
||||
|
||||
export const ImageGridItem = memo(
|
||||
({ id, ImageComponent }: ImageGridItemProps) => {
|
||||
const uri = getImageUrl(id, 100, 100)
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
alignItems: 'stretch',
|
||||
}}
|
||||
>
|
||||
<ImageComponent
|
||||
source={{ uri }}
|
||||
style={{
|
||||
flex: 1,
|
||||
width: null as any,
|
||||
height: null as any,
|
||||
margin: MARGIN,
|
||||
backgroundColor: '#eee',
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
export interface ImageGridProps {
|
||||
ImageComponent: React.ComponentType<any>
|
||||
}
|
||||
|
||||
interface ImageGridState {
|
||||
images: any[]
|
||||
itemHeight: number
|
||||
error?: any
|
||||
}
|
||||
export const ImageGrid = (props: ImageGridProps) => {
|
||||
const [images, setImages] = useState<any[]>([])
|
||||
const [itemHeight, setItemHeight] = useState(0)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
class ImageGrid extends Component<ImageGridProps, ImageGridState> {
|
||||
constructor(props: ImageGridProps) {
|
||||
super(props)
|
||||
useEffect(() => {
|
||||
fetch('https://unsplash.it/list')
|
||||
.then((res) => res.json())
|
||||
.then(this._onFetchImagesSuccess)
|
||||
.catch(this._onFetchImagesError)
|
||||
}
|
||||
.then((d) => setImages(d))
|
||||
.catch((e) => setError(e))
|
||||
}, [])
|
||||
|
||||
state: {
|
||||
images: any[]
|
||||
itemHeight: number
|
||||
error?: any
|
||||
} = {
|
||||
images: [],
|
||||
itemHeight: 0,
|
||||
}
|
||||
|
||||
_onLayout = (e: LayoutChangeEvent) => {
|
||||
const onLayout = useCallback((e: LayoutChangeEvent) => {
|
||||
const width = e.nativeEvent.layout.width
|
||||
this.setState({
|
||||
itemHeight: width / 4,
|
||||
})
|
||||
}
|
||||
setItemHeight(width / 4)
|
||||
}, [])
|
||||
|
||||
_onFetchImagesError = () => {
|
||||
this.setState({
|
||||
error: true,
|
||||
})
|
||||
}
|
||||
const getItemLayout = useCallback(
|
||||
(_: any, index: number) => {
|
||||
return { length: itemHeight, offset: itemHeight * index, index }
|
||||
},
|
||||
[itemHeight],
|
||||
)
|
||||
|
||||
_onFetchImagesSuccess = (images: any[]) => {
|
||||
this.setState({
|
||||
images,
|
||||
})
|
||||
}
|
||||
const { ImageComponent } = props
|
||||
|
||||
_getItemLayout = (_: any, index: number) => {
|
||||
const { itemHeight } = this.state
|
||||
return { length: itemHeight, offset: itemHeight * index, index }
|
||||
}
|
||||
|
||||
_renderItem = ({ item }: { item: any }) => {
|
||||
const ImageComponent = this.props.ImageComponent
|
||||
const uri = getImageUrl(item.id, 100, 100)
|
||||
return (
|
||||
<View style={styles.imageContainer}>
|
||||
<ImageComponent source={{ uri }} style={styles.image} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
_extractKey = (item: any) => {
|
||||
return item.id
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.error) {
|
||||
const renderItem = useCallback(
|
||||
({ item }: { item: any }) => {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.text}>Error fetching images.</Text>
|
||||
</View>
|
||||
<ImageGridItem id={item.id} ImageComponent={ImageComponent} />
|
||||
)
|
||||
}
|
||||
},
|
||||
[ImageComponent],
|
||||
)
|
||||
|
||||
const extractKey = useCallback((item: any) => {
|
||||
return item.id
|
||||
}, [])
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<FlatList
|
||||
onLayout={this._onLayout}
|
||||
style={styles.list}
|
||||
columnWrapperStyle={[
|
||||
styles.columnWrapper,
|
||||
{ height: this.state.itemHeight },
|
||||
]}
|
||||
data={this.state.images}
|
||||
renderItem={this._renderItem}
|
||||
numColumns={4}
|
||||
keyExtractor={this._extractKey}
|
||||
getItemLayout={this._getItemLayout}
|
||||
/>
|
||||
<StatusBarUnderlay />
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
alignItems: 'stretch',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: 'white',
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
Error fetching images.
|
||||
</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
alignItems: 'stretch',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: 'white',
|
||||
}}
|
||||
>
|
||||
<FlatList
|
||||
onLayout={onLayout}
|
||||
style={{
|
||||
marginTop: STATUS_BAR_HEIGHT,
|
||||
flex: 1,
|
||||
}}
|
||||
columnWrapperStyle={[
|
||||
{
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
marginLeft: -MARGIN,
|
||||
marginRight: -MARGIN,
|
||||
},
|
||||
{ height: itemHeight },
|
||||
]}
|
||||
data={images}
|
||||
renderItem={renderItem}
|
||||
numColumns={4}
|
||||
keyExtractor={extractKey}
|
||||
getItemLayout={getItemLayout}
|
||||
/>
|
||||
<StatusBarUnderlay />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const MARGIN = 2
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'stretch',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
text: {
|
||||
textAlign: 'center',
|
||||
},
|
||||
list: {
|
||||
marginTop: STATUS_BAR_HEIGHT,
|
||||
flex: 1,
|
||||
},
|
||||
columnWrapper: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
marginLeft: -MARGIN,
|
||||
marginRight: -MARGIN,
|
||||
},
|
||||
image: {
|
||||
flex: 1,
|
||||
width: null as any,
|
||||
height: null as any,
|
||||
margin: MARGIN,
|
||||
backgroundColor: '#eee',
|
||||
},
|
||||
imageContainer: {
|
||||
flex: 1,
|
||||
alignItems: 'stretch',
|
||||
},
|
||||
})
|
||||
|
||||
export default ImageGrid
|
||||
|
@ -6,7 +6,6 @@ import {
|
||||
TouchableOpacity,
|
||||
ViewProps,
|
||||
} from 'react-native'
|
||||
import withCacheBust from './withCacheBust'
|
||||
import FastImage, { FastImageProps, Source } from 'react-native-fast-image'
|
||||
import Section from './Section'
|
||||
import FeatureText from './FeatureText'
|
||||
@ -84,7 +83,7 @@ class PhotoExample extends Component<{}, PhotoExampleState> {
|
||||
}
|
||||
}
|
||||
|
||||
const LocalImagesExample = () => (
|
||||
export const LocalImagesExample = () => (
|
||||
<View>
|
||||
<Section>
|
||||
<FeatureText>• Local images.</FeatureText>
|
||||
@ -133,5 +132,3 @@ const styles = StyleSheet.create({
|
||||
right: 0,
|
||||
},
|
||||
})
|
||||
|
||||
export default withCacheBust(LocalImagesExample)
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { Component } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import SectionFlex from './SectionFlex'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
@ -7,70 +7,50 @@ import FeatureText from './FeatureText'
|
||||
import Button from './Button'
|
||||
// @ts-ignore
|
||||
import { createImageProgress } from 'react-native-image-progress'
|
||||
import { useCacheBust } from './useCacheBust'
|
||||
|
||||
const IMAGE_URL =
|
||||
'https://cdn-images-1.medium.com/max/1600/1*-CY5bU4OqiJRox7G00sftw.gif'
|
||||
|
||||
const Image = createImageProgress(FastImage)
|
||||
|
||||
interface PreloadExampleProps {}
|
||||
export const PreloadExample = () => {
|
||||
const [show, setShow] = useState(false)
|
||||
const { url, bust } = useCacheBust(IMAGE_URL)
|
||||
|
||||
class PreloadExample extends Component<PreloadExampleProps> {
|
||||
state = {
|
||||
show: false,
|
||||
url: IMAGE_URL,
|
||||
const preload = () => {
|
||||
FastImage.preload([{ uri: url }])
|
||||
}
|
||||
|
||||
bustCache = () => {
|
||||
const key = Math.random().toString()
|
||||
const bust = `?bust=${key}`
|
||||
// Preload images. This can be called anywhere.
|
||||
const url = IMAGE_URL + bust
|
||||
this.setState({
|
||||
url,
|
||||
show: false,
|
||||
})
|
||||
}
|
||||
|
||||
preload = () => {
|
||||
FastImage.preload([{ uri: this.state.url }])
|
||||
}
|
||||
|
||||
showImage = () => {
|
||||
this.setState({ show: true })
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<Section>
|
||||
<FeatureText text="• Preloading." />
|
||||
<FeatureText text="• Progress indication using react-native-image-progress." />
|
||||
</Section>
|
||||
<SectionFlex style={styles.section}>
|
||||
{this.state.show ? (
|
||||
<Image
|
||||
style={styles.image}
|
||||
source={{ uri: this.state.url }}
|
||||
/>
|
||||
) : (
|
||||
<View style={styles.image} />
|
||||
)}
|
||||
<View style={styles.buttons}>
|
||||
<View style={styles.buttonView}>
|
||||
<Button text="Bust" onPress={this.bustCache} />
|
||||
</View>
|
||||
<View style={styles.buttonView}>
|
||||
<Button text="Preload" onPress={this.preload} />
|
||||
</View>
|
||||
<View style={styles.buttonView}>
|
||||
<Button text="Render" onPress={this.showImage} />
|
||||
</View>
|
||||
return (
|
||||
<View>
|
||||
<Section>
|
||||
<FeatureText text="• Preloading." />
|
||||
<FeatureText text="• Progress indication using react-native-image-progress." />
|
||||
</Section>
|
||||
<SectionFlex style={styles.section}>
|
||||
{show ? (
|
||||
<Image style={styles.image} source={{ uri: url }} />
|
||||
) : (
|
||||
<View style={styles.image} />
|
||||
)}
|
||||
<View style={styles.buttons}>
|
||||
<View style={styles.buttonView}>
|
||||
<Button text="Bust" onPress={bust} />
|
||||
</View>
|
||||
</SectionFlex>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
<View style={styles.buttonView}>
|
||||
<Button text="Preload" onPress={preload} />
|
||||
</View>
|
||||
<View style={styles.buttonView}>
|
||||
<Button
|
||||
text={show ? 'Hide' : 'Show'}
|
||||
onPress={() => setShow((v) => !v)}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</SectionFlex>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
@ -92,5 +72,3 @@ const styles = StyleSheet.create({
|
||||
width: 100,
|
||||
},
|
||||
})
|
||||
|
||||
export default PreloadExample
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React from 'react'
|
||||
import { PixelRatio, StyleSheet, View } from 'react-native'
|
||||
import withCacheBust from './withCacheBust'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import Section from './Section'
|
||||
import SectionFlex from './SectionFlex'
|
||||
import FeatureText from './FeatureText'
|
||||
import { useCacheBust } from './useCacheBust'
|
||||
|
||||
const getImageUrl = (id: string, width: number, height: number) =>
|
||||
`https://source.unsplash.com/${id}/${width}x${height}`
|
||||
@ -16,42 +16,40 @@ const IMAGE_URLS = [
|
||||
getImageUrl('S7VCcp6KCKE', IMAGE_SIZE, IMAGE_SIZE),
|
||||
]
|
||||
|
||||
interface PriorityExampleProps {
|
||||
onPressReload: () => void
|
||||
bust: string
|
||||
export const PriorityExample = () => {
|
||||
const { query, bust } = useCacheBust('')
|
||||
return (
|
||||
<View>
|
||||
<Section>
|
||||
<FeatureText text="• Prioritize images (low, normal, high)." />
|
||||
</Section>
|
||||
<SectionFlex onPress={bust}>
|
||||
<FastImage
|
||||
style={styles.image}
|
||||
source={{
|
||||
uri: IMAGE_URLS[0] + query,
|
||||
priority: FastImage.priority.low,
|
||||
}}
|
||||
/>
|
||||
<FastImage
|
||||
style={styles.image}
|
||||
source={{
|
||||
uri: IMAGE_URLS[1] + query,
|
||||
priority: FastImage.priority.normal,
|
||||
}}
|
||||
/>
|
||||
<FastImage
|
||||
style={styles.image}
|
||||
source={{
|
||||
uri: IMAGE_URLS[2] + query,
|
||||
priority: FastImage.priority.high,
|
||||
}}
|
||||
/>
|
||||
</SectionFlex>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const PriorityExample = ({ onPressReload, bust }: PriorityExampleProps) => (
|
||||
<View>
|
||||
<Section>
|
||||
<FeatureText text="• Prioritize images (low, normal, high)." />
|
||||
</Section>
|
||||
<SectionFlex onPress={onPressReload}>
|
||||
<FastImage
|
||||
style={styles.image}
|
||||
source={{
|
||||
uri: IMAGE_URLS[0] + bust,
|
||||
priority: FastImage.priority.low,
|
||||
}}
|
||||
/>
|
||||
<FastImage
|
||||
style={styles.image}
|
||||
source={{
|
||||
uri: IMAGE_URLS[1] + bust,
|
||||
priority: FastImage.priority.normal,
|
||||
}}
|
||||
/>
|
||||
<FastImage
|
||||
style={styles.image}
|
||||
source={{
|
||||
uri: IMAGE_URLS[2] + bust,
|
||||
priority: FastImage.priority.high,
|
||||
}}
|
||||
/>
|
||||
</SectionFlex>
|
||||
</View>
|
||||
)
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
image: {
|
||||
flex: 1,
|
||||
@ -61,5 +59,3 @@ const styles = StyleSheet.create({
|
||||
marginVertical: 20,
|
||||
},
|
||||
})
|
||||
|
||||
export default withCacheBust(PriorityExample)
|
||||
|
@ -1,79 +1,69 @@
|
||||
import React, { Component } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import { StyleSheet, View, Text } from 'react-native'
|
||||
import withCacheBust from './withCacheBust'
|
||||
import SectionFlex from './SectionFlex'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import Section from './Section'
|
||||
import FeatureText from './FeatureText'
|
||||
import { useCacheBust } from './useCacheBust'
|
||||
|
||||
const IMAGE_URL = 'https://media.giphy.com/media/GEsoqZDGVoisw/giphy.gif'
|
||||
|
||||
interface ProgressExampleProps {
|
||||
onPressReload: () => void
|
||||
bust: string
|
||||
}
|
||||
|
||||
interface ProgressExampleState {
|
||||
mount: number
|
||||
start?: number
|
||||
progress?: number
|
||||
end?: number
|
||||
}
|
||||
|
||||
class ProgressExample extends Component<
|
||||
ProgressExampleProps,
|
||||
ProgressExampleState
|
||||
> {
|
||||
state: ProgressExampleState = {
|
||||
export const ProgressExample = () => {
|
||||
const [state, setState] = useState<{
|
||||
mount: number
|
||||
start?: number
|
||||
progress?: number
|
||||
end?: number
|
||||
}>({
|
||||
mount: Date.now(),
|
||||
start: undefined,
|
||||
progress: undefined,
|
||||
end: undefined,
|
||||
}
|
||||
})
|
||||
|
||||
render() {
|
||||
const { onPressReload, bust } = this.props
|
||||
const { mount, start, progress, end } = this.state
|
||||
return (
|
||||
<View>
|
||||
<Section>
|
||||
<FeatureText text="• Progress callbacks." />
|
||||
</Section>
|
||||
<SectionFlex onPress={onPressReload} style={styles.section}>
|
||||
<FastImage
|
||||
style={styles.image}
|
||||
source={{
|
||||
uri: IMAGE_URL + bust,
|
||||
}}
|
||||
onLoadStart={() => this.setState({ start: Date.now() })}
|
||||
onProgress={(e) =>
|
||||
this.setState({
|
||||
progress: Math.round(
|
||||
100 *
|
||||
(e.nativeEvent.loaded /
|
||||
e.nativeEvent.total),
|
||||
),
|
||||
})
|
||||
}
|
||||
onLoad={() => this.setState({ end: Date.now() })}
|
||||
onLoadEnd={() => {}}
|
||||
/>
|
||||
<Text>
|
||||
onLoadStart
|
||||
{start !== undefined && ` - ${start - mount} ms`}
|
||||
</Text>
|
||||
<Text>
|
||||
onProgress
|
||||
{progress !== undefined && ` - ${progress} %`}
|
||||
</Text>
|
||||
<Text>
|
||||
onLoad
|
||||
{end !== undefined && ` - ${end - mount} ms`}
|
||||
</Text>
|
||||
</SectionFlex>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
const { url, bust } = useCacheBust(IMAGE_URL)
|
||||
const { mount, start, progress, end } = state
|
||||
return (
|
||||
<View>
|
||||
<Section>
|
||||
<FeatureText text="• Progress callbacks." />
|
||||
</Section>
|
||||
<SectionFlex onPress={bust} style={styles.section}>
|
||||
<FastImage
|
||||
style={styles.image}
|
||||
source={{
|
||||
uri: url,
|
||||
}}
|
||||
onLoadStart={() =>
|
||||
setState((s) => ({ ...s, start: Date.now() }))
|
||||
}
|
||||
onProgress={(e) => {
|
||||
const p = Math.round(
|
||||
100 * (e.nativeEvent.loaded / e.nativeEvent.total),
|
||||
)
|
||||
setState((s) => ({
|
||||
...s,
|
||||
progress: p,
|
||||
}))
|
||||
}}
|
||||
onLoad={() => setState((s) => ({ ...s, end: Date.now() }))}
|
||||
onLoadEnd={() => {}}
|
||||
/>
|
||||
<Text>
|
||||
onLoadStart
|
||||
{start !== undefined && ` - ${start - mount} ms`}
|
||||
</Text>
|
||||
<Text>
|
||||
onProgress
|
||||
{progress !== undefined && ` - ${progress} %`}
|
||||
</Text>
|
||||
<Text>
|
||||
onLoad
|
||||
{end !== undefined && ` - ${end - mount} ms`}
|
||||
</Text>
|
||||
</SectionFlex>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
@ -90,5 +80,3 @@ const styles = StyleSheet.create({
|
||||
flex: 0,
|
||||
},
|
||||
})
|
||||
|
||||
export default withCacheBust(ProgressExample)
|
||||
|
@ -10,7 +10,7 @@ const IMAGE_URL = 'https://media.giphy.com/media/GEsoqZDGVoisw/giphy.gif'
|
||||
|
||||
const Col = (p: any) => <View style={styles.col} {...p} />
|
||||
|
||||
const ResizeModeExample = () => (
|
||||
export const ResizeModeExample = () => (
|
||||
<View>
|
||||
<Section>
|
||||
<FeatureText text="• resizeMode." />
|
||||
@ -69,5 +69,3 @@ const styles = StyleSheet.create({
|
||||
alignItems: 'center',
|
||||
},
|
||||
})
|
||||
|
||||
export default ResizeModeExample
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React from 'react'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import withCacheBust from './withCacheBust'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import Section from './Section'
|
||||
import SectionFlex from './SectionFlex'
|
||||
@ -9,36 +8,34 @@ import FeatureText from './FeatureText'
|
||||
// @ts-ignore
|
||||
import LogoImage from './images/logo.png'
|
||||
|
||||
interface TintColorExampleProps {
|
||||
onPressReload: () => void
|
||||
export const TintColorExample = () => {
|
||||
return (
|
||||
<View>
|
||||
<Section>
|
||||
<FeatureText text="Images with tint color." />
|
||||
<FeatureText text="All non-transparent pixels are changed to the color." />
|
||||
</Section>
|
||||
<SectionFlex>
|
||||
<FastImage
|
||||
style={styles.image}
|
||||
tintColor={'green'}
|
||||
source={LogoImage}
|
||||
/>
|
||||
<FastImage
|
||||
style={styles.image}
|
||||
tintColor={'#9324c3'}
|
||||
source={LogoImage}
|
||||
/>
|
||||
<FastImage
|
||||
style={styles.image}
|
||||
tintColor={'rgba(0,0,0,0.5)'}
|
||||
source={LogoImage}
|
||||
/>
|
||||
</SectionFlex>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const TintColorExample = ({ onPressReload }: TintColorExampleProps) => (
|
||||
<View>
|
||||
<Section>
|
||||
<FeatureText text="Images with tint color." />
|
||||
<FeatureText text="All non-transparent pixels are changed to the color." />
|
||||
</Section>
|
||||
<SectionFlex onPress={onPressReload}>
|
||||
<FastImage
|
||||
style={styles.image}
|
||||
tintColor={'green'}
|
||||
source={LogoImage}
|
||||
/>
|
||||
<FastImage
|
||||
style={styles.image}
|
||||
tintColor={'#9324c3'}
|
||||
source={LogoImage}
|
||||
/>
|
||||
<FastImage
|
||||
style={styles.image}
|
||||
tintColor={'rgba(0,0,0,0.5)'}
|
||||
source={LogoImage}
|
||||
/>
|
||||
</SectionFlex>
|
||||
</View>
|
||||
)
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
image: {
|
||||
flex: 1,
|
||||
@ -46,5 +43,3 @@ const styles = StyleSheet.create({
|
||||
margin: 10,
|
||||
},
|
||||
})
|
||||
|
||||
export default withCacheBust(TintColorExample)
|
||||
|
18
ReactNativeFastImageExample/src/useCacheBust.tsx
Normal file
18
ReactNativeFastImageExample/src/useCacheBust.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import { useCallback, useState } from 'react'
|
||||
|
||||
const getNewKey = () => Math.random().toString()
|
||||
|
||||
export const useCacheBust = (
|
||||
url: string,
|
||||
): { bust: () => void; url: string; query: string } => {
|
||||
const [key, setKey] = useState(getNewKey())
|
||||
const bust = useCallback(() => {
|
||||
setKey(getNewKey())
|
||||
}, [])
|
||||
const query = `?bust=${key}`
|
||||
return {
|
||||
url: `${url}${query}`,
|
||||
query,
|
||||
bust,
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
|
||||
export default function withCacheBust(BaseComponent: React.ComponentType<any>) {
|
||||
class WithCacheBust extends Component {
|
||||
state = { bust: '?bust' }
|
||||
|
||||
static displayName = `withCacheBust(${
|
||||
BaseComponent.displayName || BaseComponent.name
|
||||
})`
|
||||
|
||||
onPressReload = () => {
|
||||
// Force complete re-render and bust image cache.
|
||||
const key = Math.random().toString()
|
||||
const bust = `?bust=${key}`
|
||||
this.setState({ bust })
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<BaseComponent
|
||||
bust={this.state.bust}
|
||||
onPressReload={this.onPressReload}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return WithCacheBust
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user