React Native Tips & Tricks – Sample Code Hindari Rendering
Halo guys, artikel kali ini menampilkan contoh aplikasi sederhana untuk menghindari re-render dari aplikasi react native, masalah re-render pada aplikasi react native merupakan masalah klasik, pada saat awal membangun aplikasi terkadang kita meninggalkan berbagai re-render yang menyebabkan performa aplikasi menjadi lambat.
Hindari Rendering pada TextInput
import React from 'react';
import {
SafeAreaView,
StyleSheet,
TextInput,
TouchableOpacity,
Text,
} from 'react-native';
const UselessTextInput = () => {
const textRef = React.useRef('');
const textToRef = (text) => {
textRef.current = text;
};
const showTextInInput = () => {
console.log('value ', textRef.current);
};
console.log('render');
return (
<SafeAreaView>
<TextInput
style={styles.input}
onChangeText={textToRef}
// value={text}
/>
<TouchableOpacity onPress={showTextInInput}>
<Text>SHOW TEXT IN INPUT</Text>
</TouchableOpacity>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
input: {
height: 40,
margin: 12,
borderWidth: 1,
marginTop: 50,
padding: 10,
},
});
export default UselessTextInput;
Demo : https://snack.expo.dev/@rudiahmad/avoid-rendering-on-textinput
Sumber: https://stackoverflow.com/questions/69596418/how-to-avoid-re-rendering-text-input
Hindari Render Flatlist setiap kali memilih baris
import React, { memo, useEffect, useState } from 'react';
import { SafeAreaView, FlatList, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
import { Set } from 'immutable';
import { Button, ListItem } from 'react-native-elements';
import axios from 'axios';
const Item = ({ id, title, avatarUrl, selected, onClick }) => {
console.log(`rendering item id=${id}, selected=${selected}`);
return (
<ListItem
title={title}
leftAvatar={{ source: { uri: avatarUrl } }}
containerStyle={[
styles.item,
{ backgroundColor: selected ? '#6e3b6e' : '#f9c2ff' },
]}
underlayColor="transparent"
onPress={() => onClick(id)}
/>
);
};
function itemEq(prevItem, nextItem) {
return prevItem.id === nextItem.id && prevItem.selected === nextItem.selected;
}
// Does not make a difference, every time a row is clicked, all rows are re-rendered
const MemoizedItem = memo(Item);
// Make some difference but the behavior looks very weird. Try click around and see the log
const MemoizedItem2 = memo(Item, itemEq);
const Items = ({ data, selectedItems, onClick }) => {
console.log('rendering items');
// Replace <Item /> with <MemoizedItem /> or <MemoizedItem2 /> to see effect
const _renderItem = ({ item }) => (
<MemoizedItem
id={item.email}
title={`${item.name.title} ${item.name.first} ${item.name.last}`}
avatarUrl={item.picture.thumbnail}
selected={selectedItems.has(item.email)}
onClick={onClick}
/>
);
return (
<FlatList
data={data}
renderItem={_renderItem}
keyExtractor={(item) => item.email}
extraData={selectedItems}
/>
);
};
const App = () => {
const [items, setItems] = useState([]);
const [selectedItems, setSelectedItems] = useState(Set());
useEffect(() => {
const fetchData = async () => {
console.log('fetching data');
// Read 5 random users back
// Each user is like this:
// const results = await axios('https://randomuser.me/api/?results=5');
setItems([
{
gender: 'male',
name: {
title: 'Mr',
first: 'Harley',
last: 'Zhang',
},
location: {
street: {
number: 6470,
name: 'Buckleys Road',
},
city: 'Palmerston North',
state: 'Manawatu-Wanganui',
country: 'New Zealand',
postcode: 90911,
coordinates: {
latitude: '66.2907',
longitude: '-18.0881',
},
timezone: {
offset: '+8:00',
description: 'Beijing, Perth, Singapore, Hong Kong',
},
},
email: 'harley.zhang@example.com',
login: {
uuid: '6fda195e-3e63-476c-84d0-7c577c7b74f9',
username: 'smallbear541',
password: 'daisy1',
salt: 'p6AmByUq',
md5: '0358f2385a9936369adc89b9233f037b',
sha1: '8decc817cf32ca6e58814502bb3e54152208c5b5',
sha256:
'96ff7627348250646edd31238504271840a0cb6aaac293782f7eec1a6f884c07',
},
dob: {
date: '1987-12-07T13:00:15.244Z',
age: 33,
},
registered: {
date: '2008-01-23T19:33:01.672Z',
age: 12,
},
phone: '(474)-743-9612',
cell: '(539)-021-1315',
id: {
name: '',
value: null,
},
picture: {
large: 'https://randomuser.me/api/portraits/men/49.jpg',
medium: 'https://randomuser.me/api/portraits/med/men/49.jpg',
thumbnail: 'https://randomuser.me/api/portraits/thumb/men/49.jpg',
},
nat: 'NZ',
},
{
gender: 'male',
name: {
title: 'Mr',
first: 'Harley',
last: 'Zhang',
},
location: {
street: {
number: 6470,
name: 'Buckleys Road',
},
city: 'Palmerston North',
state: 'Manawatu-Wanganui',
country: 'New Zealand',
postcode: 90911,
coordinates: {
latitude: '66.2907',
longitude: '-18.0881',
},
timezone: {
offset: '+8:00',
description: 'Beijing, Perth, Singapore, Hong Kong',
},
},
email: 'harley@example.com',
login: {
uuid: '6fda195e-3e63-476c-84d0-7c577c7b74f9',
username: 'smallbear541',
password: 'daisy1',
salt: 'p6AmByUq',
md5: '0358f2385a9936369adc89b9233f037b',
sha1: '8decc817cf32ca6e58814502bb3e54152208c5b5',
sha256:
'96ff7627348250646edd31238504271840a0cb6aaac293782f7eec1a6f884c07',
},
dob: {
date: '1987-12-07T13:00:15.244Z',
age: 33,
},
registered: {
date: '2008-01-23T19:33:01.672Z',
age: 12,
},
phone: '(474)-743-9612',
cell: '(539)-021-1315',
id: {
name: '',
value: null,
},
picture: {
large: 'https://randomuser.me/api/portraits/men/49.jpg',
medium: 'https://randomuser.me/api/portraits/med/men/49.jpg',
thumbnail: 'https://randomuser.me/api/portraits/thumb/men/49.jpg',
},
nat: 'NZ',
},
]);
};
fetchData();
}, []);
// Does not help
const onClickUseCallBack = React.useCallback((id) => {
setSelectedItems((selectedItems) => {
const newSelectedItems = selectedItems.has(id)
? selectedItems.delete(id)
: selectedItems.add(id);
return newSelectedItems;
});
}, []);
return (
<SafeAreaView style={styles.container}>
<Items
data={items}
selectedItems={selectedItems}
onClick={onClickUseCallBack}
/>
<Button
title="Print"
onPress={() => console.log(`Printing selected items ${selectedItems}`)}
/>
</SafeAreaView>
);
};
export default App;
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: Constants.statusBarHeight,
marginHorizontal: 16,
},
item: {
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
},
});
Demo: https://snack.expo.dev/@rudiahmad/avoid-rendering-on-flatlist-selectable-flatlist-new
Sumber: https://stackoverflow.com/questions/60356434/how-to-avoid-react-native-flatlist-re-render-every-time-i-select-de-select-a-row