-
Notifications
You must be signed in to change notification settings - Fork 2
docs: create a performance optimization tips documentation #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,5 +8,6 @@ | |
| "type": "dir", | ||
| "name": "usage", | ||
| "label": "Usage" | ||
| } | ||
| }, | ||
| "performance-optimization-tips" | ||
| ] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| # Performance Optimization Tips | ||
|
|
||
| #### Wrap the `renderItem` function with `useCallback` to prevent unnecessary re-renders. | ||
|
|
||
| ```tsx | ||
| import { useCallback, useState } from 'react'; // [!code highlight] | ||
| import { ScrollView, Image, Modal } from 'react-native'; | ||
| import { GestureViewer } from 'react-native-gesture-image-viewer'; | ||
|
|
||
| function App() { | ||
| const images = [...]; | ||
| const [visible, setVisible] = useState(false); | ||
|
|
||
| // [!code highlight:3] | ||
| const renderImage = useCallback((imageUrl: string) => { | ||
| return <Image source={{ uri: imageUrl }} style={{ width: '100%', height: '100%' }} resizeMode="contain" />; | ||
| }, []); | ||
|
|
||
| return ( | ||
| <Modal visible={visible} onRequestClose={() => setVisible(false)}> | ||
| <GestureViewer | ||
| data={images} | ||
| renderItem={renderImage} | ||
| ListComponent={ScrollView} | ||
| onDismiss={() => setVisible(false)} | ||
| /> | ||
| </Modal> | ||
| ); | ||
| } | ||
| ``` | ||
|
|
||
| #### For large images, we recommend using [`expo-image`](https://docs.expo.dev/versions/latest/sdk/image/) or [`FastImage`](https://github.com/DylanVann/react-native-fast-image). | ||
|
|
||
| ```tsx | ||
| import { ScrollView, Modal } from 'react-native'; | ||
| import { GestureViewer } from 'react-native-gesture-image-viewer'; | ||
| import { Image } from 'expo-image'; // [!code highlight] | ||
|
|
||
| function App() { | ||
| const images = [...]; | ||
| const [visible, setVisible] = useState(false); | ||
|
|
||
| const renderImage = useCallback((imageUrl: string) => { | ||
| return <Image source={{ uri: imageUrl }} style={{ width: '100%', height: '100%' }} contentFit="contain" />; // [!code highlight] | ||
| }, []); | ||
|
|
||
| return ( | ||
| <Modal visible={visible} onRequestClose={() => setVisible(false)}> | ||
| <GestureViewer | ||
| data={images} | ||
| renderItem={renderImage} | ||
| ListComponent={ScrollView} | ||
| onDismiss={() => setVisible(false)} | ||
| /> | ||
| </Modal> | ||
| ); | ||
| } | ||
| ``` | ||
|
|
||
| #### For handling many images, we recommend using [`FlashList`](https://shopify.github.io/flash-list/). | ||
|
|
||
| - [FlashList Performance Guide](https://shopify.github.io/flash-list/docs/fundamentals/performance) | ||
|
|
||
| ```tsx | ||
| import { useCallback, useState } from 'react'; | ||
| import { Image, Modal } from 'react-native'; | ||
| import { GestureViewer } from 'react-native-gesture-image-viewer'; | ||
| import { FlashList } from '@shopify/flash-list'; // [!code highlight] | ||
|
|
||
| function App() { | ||
| const images = [...]; | ||
| const [visible, setVisible] = useState(false); | ||
|
|
||
| const renderImage = useCallback((imageUrl: string) => { | ||
| return <Image source={{ uri: imageUrl }} style={{ width: '100%', height: '100%' }} resizeMode="contain" />; | ||
| }, []); | ||
|
|
||
| return ( | ||
| <Modal visible={visible} onRequestClose={() => setVisible(false)}> | ||
| <GestureViewer | ||
| data={images} | ||
| renderItem={renderImage} | ||
| ListComponent={FlashList} // [!code highlight] | ||
| onDismiss={() => setVisible(false)} | ||
| /> | ||
| </Modal> | ||
| ); | ||
| } | ||
| ``` | ||
|
|
||
| #### Test on actual devices (performance may be limited in simulators). | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,5 +8,6 @@ | |
| "type": "dir", | ||
| "name": "usage", | ||
| "label": "사용법" | ||
| } | ||
| }, | ||
| "performance-optimization-tips" | ||
| ] | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,91 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # 성능 최적화 팁 | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| #### `renderItem` 함수는 `useCallback`으로 감싸서 불필요한 리렌더링을 방지하세요. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| ```tsx | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useCallback, useState } from 'react'; // [!code highlight] | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ScrollView, Image, Modal } from 'react-native'; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { GestureViewer } from 'react-native-gesture-image-viewer'; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| function App() { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const images = [...]; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const [visible, setVisible] = useState(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| // [!code highlight:3] | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const renderImage = useCallback((imageUrl: string) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return <Image source={{ uri: imageUrl }} style={{ width: '100%', height: '100%' }} resizeMode="contain" />; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }, []); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <Modal visible={visible} onRequestClose={() => setVisible(false)}> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <GestureViewer | ||||||||||||||||||||||||||||||||||||||||||||||||||
| data={images} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| renderItem={renderImage} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ListComponent={ScrollView} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| onDismiss={() => setVisible(false)} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| </Modal> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| #### 대용량 이미지의 경우 [`expo-image`](https://docs.expo.dev/versions/latest/sdk/image/)나 [`FastImage`](https://github.com/DylanVann/react-native-fast-image) 사용을 권장합니다. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| ```tsx | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ScrollView, Modal } from 'react-native'; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { GestureViewer } from 'react-native-gesture-image-viewer'; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Image } from 'expo-image'; // [!code highlight] | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| function App() { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const images = [...]; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const [visible, setVisible] = useState(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| const renderImage = useCallback((imageUrl: string) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return <Image source={{ uri: imageUrl }} style={{ width: '100%', height: '100%' }} contentFit="contain" />; // [!code highlight] | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }, []); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+34
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
-import { ScrollView, Modal } from 'react-native';
+import { useCallback, useState } from 'react';
+import { ScrollView, Modal } from 'react-native';📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <Modal visible={visible} onRequestClose={() => setVisible(false)}> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <GestureViewer | ||||||||||||||||||||||||||||||||||||||||||||||||||
| data={images} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| renderItem={renderImage} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ListComponent={ScrollView} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| onDismiss={() => setVisible(false)} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| </Modal> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| #### 많은 수의 이미지를 다룰 때는 [`FlashList`](https://shopify.github.io/flash-list/) 사용을 권장합니다. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| - [FlashList Performance 가이드](https://shopify.github.io/flash-list/docs/fundamentals/performance) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| ```tsx | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useCallback, useState } from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Image, Modal } from 'react-native'; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { GestureViewer } from 'react-native-gesture-image-viewer'; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { FlashList } from '@shopify/flash-list'; // [!code highlight] | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| function App() { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const images = [...]; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const [visible, setVisible] = useState(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| const renderImage = useCallback((imageUrl: string) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return <Image source={{ uri: imageUrl }} style={{ width: '100%', height: '100%' }} resizeMode="contain" />; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }, []); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <Modal visible={visible} onRequestClose={() => setVisible(false)}> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <GestureViewer | ||||||||||||||||||||||||||||||||||||||||||||||||||
| data={images} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| renderItem={renderImage} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ListComponent={FlashList} // [!code highlight] | ||||||||||||||||||||||||||||||||||||||||||||||||||
| onDismiss={() => setVisible(false)} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| </Modal> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| #### 디바이스에서 테스트하세요. (시뮬레이터에서는 성능이 제한될 수 있습니다.) | ||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing React hook imports in second snippet
The example invokes
useCallbackanduseStatebut forgets to import them, resulting in a runtime error if readers copy the code verbatim.🤖 Prompt for AI Agents