From 5946d3321eb49ee770b791307b4b744908973c88 Mon Sep 17 00:00:00 2001 From: Dylan Vann Date: Mon, 27 Sep 2021 17:39:25 +0700 Subject: [PATCH] chore: convert examples to hooks (#830) --- ReactNativeFastImageExample/.eslintrc.js | 1 + .../__tests__/App-test.tsx | 2 +- .../src/AutoSizeExample.tsx | 111 ++++----- .../src/BorderRadiusExample.tsx | 55 ++-- .../src/DefaultImageGrid.tsx | 2 +- .../src/FastImageExamples.tsx | 18 +- .../src/FastImageGrid.tsx | 2 +- .../src/GifExample.tsx | 30 +-- ReactNativeFastImageExample/src/ImageGrid.tsx | 235 +++++++++--------- .../src/LocalImagesExample.tsx | 5 +- .../src/PreloadExample.tsx | 92 +++---- .../src/PriorityExample.tsx | 70 +++--- .../src/ProgressExample.tsx | 118 ++++----- .../src/ResizeModeExample.tsx | 4 +- .../src/TintColorExample.tsx | 57 ++--- .../src/useCacheBust.tsx | 18 ++ .../src/withCacheBust.tsx | 29 --- 17 files changed, 379 insertions(+), 470 deletions(-) create mode 100644 ReactNativeFastImageExample/src/useCacheBust.tsx delete mode 100644 ReactNativeFastImageExample/src/withCacheBust.tsx diff --git a/ReactNativeFastImageExample/.eslintrc.js b/ReactNativeFastImageExample/.eslintrc.js index 09eb1da..767348b 100644 --- a/ReactNativeFastImageExample/.eslintrc.js +++ b/ReactNativeFastImageExample/.eslintrc.js @@ -3,5 +3,6 @@ module.exports = { extends: '@react-native-community', rules: { semi: ['error', 'never'], + 'react-native/no-inline-styles': 'off', }, } diff --git a/ReactNativeFastImageExample/__tests__/App-test.tsx b/ReactNativeFastImageExample/__tests__/App-test.tsx index cc1ca89..3e0f5fd 100644 --- a/ReactNativeFastImageExample/__tests__/App-test.tsx +++ b/ReactNativeFastImageExample/__tests__/App-test.tsx @@ -10,5 +10,5 @@ import App from '../src' import renderer from 'react-test-renderer' it('renders correctly', () => { - renderer.create() + renderer.create() }) diff --git a/ReactNativeFastImageExample/src/AutoSizeExample.tsx b/ReactNativeFastImageExample/src/AutoSizeExample.tsx index 99da7f8..75dfb86 100644 --- a/ReactNativeFastImageExample/src/AutoSizeExample.tsx +++ b/ReactNativeFastImageExample/src/AutoSizeExample.tsx @@ -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 ( - - ) - } + const ratio = dimensions.height / dimensions.width + return props.width * ratio + }, [dimensions.height, dimensions.width, props.defaultHeight, props.width]) + return ( + + ) } -interface AutoSizeExampleProps { - onPressReload: () => void - bust: boolean +export const AutoSizeExample = () => { + const { bust, url } = useCacheBust(GIF_URL) + return ( + +
+ +
+ + + +
+ ) } -const AutoSizeExample = ({ onPressReload, bust }: AutoSizeExampleProps) => ( - -
- -
- - - -
-) - const styles = StyleSheet.create({ image: { backgroundColor: '#ddd', @@ -90,5 +77,3 @@ const styles = StyleSheet.create({ flex: 0, }, }) - -export default withCacheBust(AutoSizeExample) diff --git a/ReactNativeFastImageExample/src/BorderRadiusExample.tsx b/ReactNativeFastImageExample/src/BorderRadiusExample.tsx index 2f7216e..d477116 100644 --- a/ReactNativeFastImageExample/src/BorderRadiusExample.tsx +++ b/ReactNativeFastImageExample/src/BorderRadiusExample.tsx @@ -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 ( + +
+ +
+ + + + +
+ ) } -const BorderRadiusExample = ({ - onPressReload, - bust, -}: BorderRadiusExampleProps) => ( - -
- -
- - - - -
-) - const styles = StyleSheet.create({ imageSquare: { borderRadius: 50, @@ -64,5 +59,3 @@ const styles = StyleSheet.create({ right: 0, }, }) - -export default withCacheBust(BorderRadiusExample) diff --git a/ReactNativeFastImageExample/src/DefaultImageGrid.tsx b/ReactNativeFastImageExample/src/DefaultImageGrid.tsx index 65f8a0d..46b139c 100644 --- a/ReactNativeFastImageExample/src/DefaultImageGrid.tsx +++ b/ReactNativeFastImageExample/src/DefaultImageGrid.tsx @@ -1,6 +1,6 @@ import React from 'react' import { Image } from 'react-native' -import ImageGrid from './ImageGrid' +import { ImageGrid } from './ImageGrid' const DefaultImageGrid = () => diff --git a/ReactNativeFastImageExample/src/FastImageExamples.tsx b/ReactNativeFastImageExample/src/FastImageExamples.tsx index e251bdd..bd0792b 100644 --- a/ReactNativeFastImageExample/src/FastImageExamples.tsx +++ b/ReactNativeFastImageExample/src/FastImageExamples.tsx @@ -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 = () => ( diff --git a/ReactNativeFastImageExample/src/FastImageGrid.tsx b/ReactNativeFastImageExample/src/FastImageGrid.tsx index 9a75eda..ee32192 100644 --- a/ReactNativeFastImageExample/src/FastImageGrid.tsx +++ b/ReactNativeFastImageExample/src/FastImageGrid.tsx @@ -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 = () => diff --git a/ReactNativeFastImageExample/src/GifExample.tsx b/ReactNativeFastImageExample/src/GifExample.tsx index fc3b9da..375437f 100644 --- a/ReactNativeFastImageExample/src/GifExample.tsx +++ b/ReactNativeFastImageExample/src/GifExample.tsx @@ -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 ( + +
+ +
+ + + +
+ ) } -const GifExample = ({ onPressReload, bust }: GifExampleProps) => ( - -
- -
- - - -
-) - const styles = StyleSheet.create({ image: { backgroundColor: '#ddd', @@ -34,5 +32,3 @@ const styles = StyleSheet.create({ flex: 0, }, }) - -export default withCacheBust(GifExample) diff --git a/ReactNativeFastImageExample/src/ImageGrid.tsx b/ReactNativeFastImageExample/src/ImageGrid.tsx index eea54e6..e9d5d86 100644 --- a/ReactNativeFastImageExample/src/ImageGrid.tsx +++ b/ReactNativeFastImageExample/src/ImageGrid.tsx @@ -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 ( + + + + ) + }, +) + +export interface ImageGridProps { ImageComponent: React.ComponentType } -interface ImageGridState { - images: any[] - itemHeight: number - error?: any -} +export const ImageGrid = (props: ImageGridProps) => { + const [images, setImages] = useState([]) + const [itemHeight, setItemHeight] = useState(0) + const [error, setError] = useState(null) -class ImageGrid extends Component { - 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 ( - - - - ) - } - - _extractKey = (item: any) => { - return item.id - } - - render() { - if (this.state.error) { + const renderItem = useCallback( + ({ item }: { item: any }) => { return ( - - Error fetching images. - + ) - } + }, + [ImageComponent], + ) + + const extractKey = useCallback((item: any) => { + return item.id + }, []) + + if (error) { return ( - - - + + + Error fetching images. + ) } + + return ( + + + + + ) } - -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 diff --git a/ReactNativeFastImageExample/src/LocalImagesExample.tsx b/ReactNativeFastImageExample/src/LocalImagesExample.tsx index 720dfb9..2792c51 100644 --- a/ReactNativeFastImageExample/src/LocalImagesExample.tsx +++ b/ReactNativeFastImageExample/src/LocalImagesExample.tsx @@ -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 = () => (
• Local images. @@ -133,5 +132,3 @@ const styles = StyleSheet.create({ right: 0, }, }) - -export default withCacheBust(LocalImagesExample) diff --git a/ReactNativeFastImageExample/src/PreloadExample.tsx b/ReactNativeFastImageExample/src/PreloadExample.tsx index e65c1c1..d4e76e0 100644 --- a/ReactNativeFastImageExample/src/PreloadExample.tsx +++ b/ReactNativeFastImageExample/src/PreloadExample.tsx @@ -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 { - 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 ( - -
- - -
- - {this.state.show ? ( - - ) : ( - - )} - - -