深入了解React Native FlatList

2,089 阅读6分钟

考虑一种情况,你想显示一个来自API的项目列表。例如,Coffee API的响应看起来像这样。

Coffee API List Response

向客户端显示的一个可能的方法是对这个数组使用map 方法,像这样。

const data = getDataFromAPI(); 
return (
  <View style={styles.container}>
    {data && (
      <View>
        <Text> Your data has loaded! Here is the result:</Text>
        {data.map((item) => (
          <Text key={item.id}> {item.name}</Text>
        ))}
      </View>
    )}
  </View>
);

在这里,我们正在使用条件渲染来检查数据是否已经加载。如果是真的,我们将通知用户并在屏幕上显示列表。
这将是输出。

Coffee API Data Loaded but List is Not Visible

这段代码应该是有效的。那么为什么我们的列表不可见呢?

这就是 [FlatList](https://reactnative.dev/docs/flatlist)来缓解这个问题。它是一个React Native组件,允许你以零麻烦和最小的代码渲染列表。

FlatList 语法

FlatList 使用以下语法。

import { FlatList } from "react-native";
<FlatList
  data={
    //the array to render
  }
  keyExtractor={
    // Extract keys for each item in the array
  }
  renderItem={
    //each item from the array will be rendered here
  }
/>;

  • data 道具中,你将输入你想显示的数组。这可以是来自API的JSON数据
  • keyExtractor 道具将为数组中的每个项目检索一个唯一的键
    注意,如果你的数组包含一个keyid 字段,你不需要包括这个道具。默认情况下,FlatList 将寻找keyid 属性。
  • renderItem 将告诉React Native如何渲染列表中的项目。

使用示例

现在我们已经掌握了语法,让我们用它来渲染我们的列表。

//the data array contains our array of items. 
const data = [{id:1, title:"Black", description:""},... ]; 
const Item = ({ title, description }) => (
  <View>
    <Text style={styles.title}>{title} </Text>
    <Text>{description} </Text>
  </View>
);

const renderItem = ({ item }) => (
  <Item title={item.title} description={item.description} />
);
return (
  <View style={styles.container}>
    {data && (
      <FlatList
        data={data}
        renderItem={renderItem}
        keyExtractor={(item) => item.id}
      />
    )}
  </View>
);

让我们一块一块地解构这段代码。

  • Item 组件将接受两个道具:titledescription 。这个组件将把它们显示在用户界面上
  • renderItem 函数将为数组中的每个项目渲染Item 组件。因此,这将显示每个对象的titledescription 字段。
  • 此外,keyExtractor 道具告诉React Native,它应该使用id 字段作为一个键。
  • 最后,我们使用条件渲染来渲染带有FlatList React Native元素的数据。

Sample FlatList with Coffee API

显示来自API的数据

在现实世界中,React Native开发者可能需要处理将API数据渲染成列表的问题。

在下面的代码中,我们从Coffee API中获取数据并将其插入我们的FlatList组件中。

export default function App() {
  const [data, setData] = useState(null);

  const getData = async () => {
    const resp = await fetch("https://api.sampleapis.com/coffee/hot");
    const data = await resp.json();
    setData(data);
  };
  //on first mount, fetch data.
  useEffect(() => {
    getData();
  }, []);

  const Item = ({ title, description, index }) => (
    <View>
      <Text style={styles.title}>
        {index}. {title}
      </Text>
      <Text> {description} </Text>
    </View>
  );

  const renderItem = ({ item, index }) => (
    <Item description={item.description} title={item.title} index={index} />
  );

  return (
    <View style={styles.container}>
      {data && (
        <FlatList
          data={data}
          renderItem={renderItem}
        />
      )}
    </View>
  );
}

从这段代码中可以得出一些推论。

  • App 组件第一次被渲染时,React调用了getData 方法。这将向API发出一个GET 的请求。
  • renderItem 函数中,我们也在使用index 参数。这是与数组中的当前项目相对应的索引。
  • 请注意,我们没有使用keyExtractor 道具。这是因为已经有了一个id 字段,所以FlatList 将使用这个字段作为密钥

RN FlatList Displaying Data from an API

FlatList 自定义

头部组件

FlatList也有对标题组件的支持。这在你想在联系人清单的顶部显示一个搜索栏的情况下会很方便。
ListHeaderComponent 道具可以帮助你做到这一点。

import { Divider } from "react-native-elements";

const header = () => {
  return (
    <View>
      <Text style={styles.title}> Coffee list</Text>
      <Divider orientation="vertical" />
    </View>
  );
};

return (
  <View style={styles.container}>
    {data && (
      <FlatList
        ListHeaderComponent={header}
        data={data}
        renderItem={renderItem}
      />
    )}
  </View>
);

在上面的代码块中,我们首先创建了一个header 函数,然后将其传递给我们的ListHeaderComponent 道具。这将在FlatList 组件的顶部输出一个简单的TextDivider 组件。

FlatList Header Component

页脚组件

考虑一种情况,即用户已经一路向下滚动,并想再向上滚动。在这里,明智的做法是显示一个按钮,让客户自动回到上面。在这种情况下,你可以为你的列表添加一个页脚组件。这将表明列表已经结束。

你可以通过ListFooterComponent 这样的道具来做。

//This will be our footer component
const endComponent = () => {
  return (
    <View>
      <Divider orientation="vertical" />
      <Text style={styles.text}> List ended</Text>
    </View>
  );
};

return (
  <View style={styles.container}>
    {data && (
      <FlatList
        ListFooterComponent={endComponent}
        data={data}
        renderItem={renderItem}
      />
    )}
  </View>
);

FlatList Footer Component

分隔符

分隔符组件帮助用户区分列表中的每个元素。这有助于获得更好的用户体验和界面。

为了达到这个目的,可以像这样使用ItemSeparatorComponent 道具。

const separator = () => {
  return <Divider orientation="vertical" />;
};

return (
  <View style={styles.container}>
    {data && (
      <FlatList
        ItemSeparatorComponent={separator}
        data={data}
        renderItem={renderItem}
      />
    )}
  </View>
);

RN FlatList Separators

处理空列表

假设你在React Native中建立了一个记事本应用。如果用户没有记录,就适合显示 "没有找到笔记 "的信息。

对于这一点,ListEmptyComponent 这个道具很有用。

const data = []; //empty array
const handleEmpty = () => {
  return <Text style={styles.title}> No data present!</Text>;
};
return (
  <View style={styles.container}>
    {!data && <Text> Loading</Text>}
    {data && (
      <FlatList
        ListEmptyComponent={handleEmpty}
        data={data}
        renderItem={renderItem}
      />
    )}
  </View>
);

RN FlatList Empty List

FlatList 导航方法

FlatList 还包括一些与滚动有关的操作的实用函数。

滚动到最后

假设你有一个包含数百个项目的列表。在这里,显示一个让用户一直往下走的按钮会很好。这将带来更好的用户体验,因为用户不必手动滚动到底部,从而节省时间。

为了实现这一点,你可以像这样使用scrollToEnd 方法。

const list = useRef(null);

const press = () => {
  list.current.scrollToEnd({ animated: true });
};
const header = () => {
  return <Button onPress={() => press()} title="Go to end" />;
};

return (
  <View style={styles.container}>
    {!data && <Text> Loading</Text>}
    {data && (
      <FlatList
        ref={list}
        ListHeaderComponent={header}
        data={data}
        renderItem={renderItem}
      />
    )}
  </View>
);

在这段代码中,我们创建了一个useRef Hook,它将允许我们访问FlatList'的实用函数。当用户点击Button 元素时,应用程序将执行scrollToEnd 方法。

FlatList Scroll to End Button

导航到一个特定的索引项

我们甚至可以像这样通过调用scrollToIndex 方法滚动到一个特定的项目。

const list = useRef(null);

const press = () => {
  //scroll to the 12th item in the index.
  list.current.scrollToIndex({ animated: true, index: 12 });
};

const header = () => {
  return <Button onPress={() => press()} title="Go to 12th index" />;
};

return (
  <View style={styles.container}>
    {!data && <Text> Loading</Text>}
    {data && (
      <FlatList
        ref={list}
        ListHeaderComponent={header}
        data={data}
        renderItem={renderItem}
      />
    )}
  </View>
);

在这个代码片段中,我们告诉React,如果用户点击按钮,那么它应该把用户重定向到数组中的第十二个项目。

Navigating to a Specific Index

最佳实践

避免使用匿名函数

尽量避免在你的FlatList 中使用匿名函数。React Native团队建议这样做,这样函数就不会在每次显示你的列表时重新创建自己。这样可以节省内存和CPU资源。

//correct way: no anonymous functions
const renderItem = ({ item, index }) => (
  <Text>
    {index}. {item.title}
  </Text>
);
{
  data && (
    <FlatList
      data={data}
      keyExtractor={(item) => item.id}
      renderItem={renderItem}
    />
  );
}
//the wrong way. Steer clear from this:
{
  data && (
    <FlatList
      data={data}
      keyExtractor={(item) => item.id}
      renderItem={({ item, index }) => (
        <Text>
          {index}.{item.title}
        </Text>
      )}
    />
  );
}

更轻的组件

你的组件越重,它们占用的内存就越多。在你的列表项上显示尽可能少的信息。作为奖励,这使你的用户界面看起来更干净。

即使你确实有需要显示大量文字的项目,你也可以使用React Navigation。如果用户点击任何项目,React将引导他们到一个单独的页面,显示其余的细节。下面是一个例子。

RN FlatList with Too Much TextRN FlatList with Read More

结语

在这篇文章中,我们介绍了React Native的FlatList ,它的有用功能和自定义选项。如果你想在你的React Native应用中渲染列表,它是一个重要的组件。它使用起来绝对轻而易举,而且坚如磐石。

谢谢你的阅读!编码愉快。

The postA deep dive into React Native FlatList appearedfirst on LogRocketBlog.