generated at
FlatListの最適化




FlatListのパフォーマンス的改善を施す

どうやって計測するか
もしくは、どの指標で計測するか


FlatListのpropsを使って改善する
removeClippedSubviews ref
default: iosではfalse, androidではtrue
trueにするとviewport外のViewはNativie View階層から切り離され、スクロールのパフォーマンスが向上する
Native/Main Threadで費やされる時間が削減されframeがdropするリスクが軽減される
複雑なことをしている場合は、コンテンツの欠落などのバグが生じうる
maxToRenderPerBatch ref
default: 10
1回のスクロールごとに描画するアイテムの量
大きくすると表示的に空白になる箇所が減るがパフォーマンスが低下する
これの3
updateCellsBatchingPeriod ref
バッチごとの描画の遅延msを指定する
上のmaxToRenderPerBatchと組み合わせる
長時間待って多くのアイテムを取得する、短時間ごとに小さなアイテムを取得する、などの調整ができる
initialNumToRender ref
最初のbatchで描画するアイテム数
これを調節して、画面に収まる分だけ描画するなど
windowSize ref
default: 21
1はViewportの高さ
この値を小さくすると同時にmountするアイテム数が減り、メモリが節約される
デフォルトでかくね?mrsekut
認識が間違っているのか
よくわからんmrsekut
これの4
getItemLayout ref
全てのアイテムの高さが同じ場合はこれを使おう
FlatListが非同期レイアウト計算をする必要がなくなる
keyExtractorを使う
一意のkeyを指定する
これの7

renderItemに渡すコンポーネントはシンプルにする
あまり再利用性を目指さないほうがいい ref
1箇所でのみ複雑に使われるなら、それのために新しいコンポーネントを作るべき
できるだけ小さいロジックで作る
複雑になるほど重くなる
これの6
重い画像は避ける
これの2
>use as little information as possible in your list.
リストの情報はできるだけ使用しない、だと..






再描画を避ける工夫をする
最小コストのmemo化 ref
これの8
renderItemに無名関数を使わない
ts
renderItem = ({ item }) => (<View key={item.key}><Text>{item.title}</Text></View>); render(){ // ... <FlatList data={items} renderItem={renderItem} /> // ... }
extraData
アイテムの一つを更新するためにdataを更新すると、FlatList全て(?)が再描画されてしまう
なのでextraDataを更新する
アイテムがチェックされているかどうかなどは、FlatListを使っているコンポーネントが管理しないといけない
ts
const P = () => { const [selectedId, setSelectedId] = useState() // 子の状態を管理 const C = () => <H onPress={setSectedId}></H> // 子 return ( <FlatList renderItem={C} extraData={selectedId} /> ) }
複数選択できるなら無理じゃんmrsekut
ts
class SelectableItem extends React.Component { constructor() { super(); this.handleOnPress = this.handleOnPress.bind(this); } shouldComponentUpdate(nextProps) { const { isSelected } = this.props; return isSelected !== nextProps.isSelected; } handleOnPress() { const { onPress } = this.props; onPress(); } render() { const { isSelected, text } = this.props; const textColor = isSelected ? 'blue' : 'black'; return ( <TouchableOpacity onPress={this.handleOnPress}> <View> <Text style={{ color: textColor }}>{text}</Text> </View> </TouchableOpacity> ); } } class SelectList extends React.Component { constructor() { super(); this.handleOnPressItem = this.handleOnPressItem.bind(this); this.state = { selected: new Map(), }; } onPressItem(id) { this.setState((state) => { const selected = new Map(state.selected); selected.set(id, !selected.get(id)); return { selected }; }); } renderItem({ item }) { const { selected } = this.state; return ( <SelectableItem id={item.id} onPressItem={this.handleOnPressItem} selected={!!selected.get(item.id)} title={item.title} /> ); } render() { const { data } = this.props; return ( <FlatList data={data} extraData={this.state} keyExtractor={item => item.id} renderItem={this.renderItem} /> ); } }
まじ?FCの場合でも同じ様に?
renderItemをuseCallbackしてる
さらにrenderitemはmemoでwrap




sample ref
ts
// render item function, outside from class's `render()` const renderItem = ({ item }) => (<Text key={item.key}>{item.key}</Text>); // we set the height of item is fixed const getItemLayout = (data, index) => ( {length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index} ); const items = [{ key: 'a' }, { key: 'b'}, ...+400]; function render () => ( <FlatList data={items} renderItem={renderItem} getItemLayout={getItemLayout} initialNumToRender={5} maxToRenderPerBatch={10} windowSize={10} /> );



headerやfooterのコンポーネントも無名じゃない方がいいのか





参考
本家とほぼ同じだが↑のほうが若干充実している
特に再描画について



FlatListはpropsのわたし方によってはかなり非効率になりうる気がする
プロパティが多いし、描画かどうかをconsoleで調べられないので気にしないがち
そんでもって利用頻度が高い
例えばonRefreshやonEndReachedをpropsで渡してい
ここはuseWhyDidUpdateで調べられないので、調査できていないmrsekut
その割にアプリ内の多くの場所で使われているのでちゃんと調べておきたいmrsekutmrsekut
コンポーネントを渡している
インラインでもいいのかどうか #??
同値だが再描画を防ぐ
全ての関数はuseCallbackする
keyExtractor, ListHeaderComponent, ListFooterComponent
keyExtractorもmemo化するのメンドすぎる..mrsekut
styleは外部に移動させる
renderItemを無名関数で指定しない ref
全てのprop使った場合のexample見たいは😡
理想の状態を見たいわmrsekut
renderItemって再描画されなくなるの?