使用 axios 获取数据并渲染 flatList

fetching data with axios and rendering flatList

我一直在试用 Axios 和 React Native,但我遇到了麻烦。 flatList 不呈现数据并给我一个警告 'warning: Each child in a list should have a unique "key" prop.'

我已经在线查找了几个小时,但找不到解决方案。我能找到的最接近的事情是设置 keyExtractor,我就是这么做的。

这是我的代码:

import React, { useEffect, useState } from 'react';
import { ActivityIndicator, FlatList, Text, View } from 'react-native';
import Axios from 'axios';

export default App = () => {
  const [isLoading, setLoading] = useState(true);
  const [data, setData] = useState([]);

  useEffect(() => {
    Axios.get('https://reactnative.dev/movies.json')
      .then(({data}) => setData({data}))
      .catch((error) => console.error(error))
      .finally(() => setLoading(false));
  });

  return (
    <View style={{ flex: 1, padding: 24 }}>
      {isLoading ? <ActivityIndicator/> : (
        <FlatList
          data={JSON.stringify(data)}
          keyExtractor={({ id }, index) => id}
          renderItem={({ item }) => (
            <Text>{item.title}, {item.releaseYear}</Text>
          )}
        />
      )}
    </View>
  );
};

我明白这可能是一个非常简单的问题,但如果你能帮助我,我将不胜感激。

我认为值得一提的是它与 fetch 一起使用。所以我认为问题出在 axios.get 请求而不是 flatList.

这里是 API 如果它有任何用处:

{
  "title": "The Basics - Networking",
  "description": "Your app fetched this from a remote endpoint!",
  "movies": [
    { "id": "1", "title": "Star Wars", "releaseYear": "1977" },
    { "id": "2", "title": "Back to the Future", "releaseYear": "1985" },
    { "id": "3", "title": "The Matrix", "releaseYear": "1999" },
    { "id": "4", "title": "Inception", "releaseYear": "2010" },
    { "id": "5", "title": "Interstellar", "releaseYear": "2014" }
  ]
}

编辑:在尝试了此处的答案后,它不再发出警告,而是呈现一个空列表。

在渲染项目中,您需要提供文本的键:

      renderItem={({ item }) => (
        <Text key={item.title}>{item.title}, {item.releaseYear}</Text>
      )}

就是这样,假设item.title是唯一的。

为了提供更多关于为什么这是一个问题的上下文,React 使用键来识别列表中的哪些项目在渲染之间是相同的,因此它可以比在每个渲染上创建全新的项目做更少的工作。本质上,React 使用键来确定哪些元素是同一元素。因此,如果您在每次渲染之间更改键,React 将假定该元素是一个新元素并在安装新元素之前卸载旧元素。

可以使用索引作为键,但这比使用唯一标识符的性能要差。因为使用索引意味着如果您对列表进行排序或以其他方式重新排序,它必须做更多的工作来协调差异,而不仅仅是移动 dom 个节点。

编辑: 除了最初的问题,我已经解决了您遇到的其他问题。

useEffect 调用需要使用依赖项数组,因此不会在每次重新渲染时都调用它。

axios 调用的数据需要使用 data.movies 才能获取电影数组。

传递到 FlatList 的数据不需要被字符串化,因为这会导致它将每个字符串化字符呈现为一个新行(逗号)。

https://snack.expo.io/rVzXb!gsJ

试试这个

        FlatList
          data={JSON.stringify(data)}
          keyExtractor={(id, index) => index.toString()}
          renderItem={({ item }) => (
            <Text>{item.title}, {item.releaseYear}</Text>
          )}
        />

我想你需要日志数据来调试。 第一:setData({data}) 是错误的。 第二:不要使用JSON.stringify(data)。 第三:keyExtractor={({ id }, index) => id}是错误的

试试下面的代码

import React, { useEffect, useState } from 'react';
import { ActivityIndicator, FlatList, Text, View } from 'react-native';
import Axios from 'axios';

export default App = () => {
  const [isLoading, setLoading] = useState(true);
  const [data, setData] = useState([]);

  useEffect(() => {
    Axios.get('https://reactnative.dev/movies.json')
      .then(({ data }) => {
        console.log("defaultApp -> data", data.movies)
        setData(data.movies)
      })
      .catch((error) => console.error(error))
      .finally(() => setLoading(false));
  }, []);

  return (
    <View style={{ flex: 1, padding: 24 }}>
      {isLoading ? <ActivityIndicator /> : (
        <FlatList
          data={data}
          keyExtractor={(item, index) => {
            // console.log("index", index)
            return index.toString();
          }}
          renderItem={({ item }) => {
            console.log("item", item)
            return (
              <Text style={{ flex: 1, backgroundColor: 'red' }}>{item.title}, {item.releaseYear}</Text>
            )
          }}
        />
      )}
    </View>
  );
};

keyExtractor={({ id }, index) => id.toString()}

密钥最初以数字形式出现,您必须将其转换为字符串。