# FlatList

[官方文檔](https://facebook.github.io/react-native/docs/flatlist.html)    [中文](https://reactnative.cn/docs/0.44/flatlist.html)    [React Native Express](http://www.reactnativeexpress.com/flatlist)

以下內容來自官網高性能的列表組件 只渲染顯示於螢幕內的內容，只更新資料有變動的item 支持以下常用功能:

* 完全跨平台
* 水平佈局
* 行組件顯示或隱藏時可配置回調事件
* 列表的頭部組件
* 列表的尾部組件
* 自定義行間分隔線
* 下拉刷新
* 上拉加載
* 跳轉到指定的index（第index個item）
  * 此方法必須設置getItemLayout。getItemLayout中需帶入每個item的高度，目前找到的都是固定item高度，若item的高度是動態的情況下..尚無頭緒..
  * length=>當前item的高度\
    offset=>目前總高度

    ```
    getItemLayout={(data, index) => (
     {length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index}
    )}
    ```

### 例子<br>

#### 最簡單的例子

```
<FlatList
  data={[{key: 'a'}, {key: 'b'}]}
  renderItem={({item}) => <Text>{item.key}</Text>}
/>
```

#### 較複雜的例子&#x20;

演示如何利用PureComponent來進一步優化性能和減少bug產生的可能（這段需要了解shouldComponentUpdate的機制，以及Component和PureComponent的不同）

* 對於MyListItem組件來說，其onPressItem屬性使用箭頭函數而非bind的方式進行綁定，使其不會在每次列表重新render時生成一個新的函數，從而保證了props的不變性（當然前提是id、selected和title也沒變），避免了觸發自身無謂的重新render。換句話說，如果你是用bind來綁定onPressItem，每次都會生成一個新的函數，導致props在===比較時返回false，從而觸發自身的一次不必要的重新render。
* 給FlatList指定extraData={this.state}屬性，是為了保證state.selected變化時，能夠正確觸發FlatList的更新。如果不指定此屬性，則FlatList不會觸發更新，因為它是一個PureComponent，其props在===比較中沒有變化則不會觸發更新。
* keyExtractor屬性指定使用id作為列表每一項的key。

```
class MyListItem extends React.PureComponent {
  _onPress = () => {
    this.props.onPressItem(this.props.id);
  };

  render() {
    return (
      <SomeOtherWidget
        {...this.props}
        onPress={this._onPress}
      />
    )
  }
}

class MyList extends React.PureComponent {
  state = {selected: (new Map(): Map<string, boolean>)};

  _keyExtractor = (item, index) => item.id;

  _onPressItem = (id: string) => {
    // updater functions are preferred for transactional updates
    this.setState((state) => {
      // copy the map rather than modifying state.
      const selected = new Map(state.selected);
      selected.set(id, !selected.get(id)); // toggle
      return {selected};
    });
  };

  _renderItem = ({item}) => (
    <MyListItem
      id={item.id}
      onPressItem={this._onPressItem}
      selected={!!this.state.selected.get(item.id)}
      title={item.title}
    />
  );

  render() {
    return (
      <FlatList
        data={this.props.data}
        extraData={this.state}
        keyExtractor={this._keyExtractor}
        renderItem={this._renderItem}
      />
    );
  }
}
```

給予的data若有變動，請使用...data 此方法給予新的data，通知flatlist資料有變動

### sample code

![](https://bambooooo.gitbooks.io/react-native/content/React%20Native/images/basic/flatlist/flatlist.png)

```
import React, {Component} from 'react'
import {StyleSheet, View, FlatList, Text} from 'react-native'

var data = [
    {"id":1, title:"title-1"},
    {"id":2, title:"title-2"},
    {"id":3, title:"title-3"},
    {"id":4, title:"title-4"},
    {"id":5, title:"title-5"},
    {"id":6, title:"title-6"},
    {"id":7, title:"title-7"}
]
export default class RecordList extends Component {
  render() {
    return(
      <FlatList
        data={data}
        keyExtractor={(item, index) => item.id}
        renderItem={({item, index}) => <Text>{item.title}</Text>}
        ItemSeparatorComponent={() => this.separator()} 
        onEndReachedThreshold = {0.5}
        onEndReached={()=> {/*快到底了，要加載更多資料..等*/} }
        ListFooterComponent={() => this.footerComponent()}
       />
    );
  }

  separator() {
    return <View style={styles.separator} />
  }

  footerComponent() {
    return (
    <View style={styles.footerView}>
        <Text>最後一筆</Text>
    </View>
    )
  }

}

const styles = StyleSheet.create({
  separator: {
    height: 1,
    backgroundColor: 'red',
  },
  footerView: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
  },
});
```

### 參考

* <https://juejin.im/post/5978647d51882517905f652e>
* <http://blog.csdn.net/qq_34161388/article/details/72897292>
* <https://dev-blog.apollodata.com/loading-data-into-react-natives-flatlist-9646fa9a199b>
* <http://www.jianshu.com/p/3def7687594c>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://twins-bamboo.gitbook.io/react-native-note/basic/flatlist.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
