【问题标题】:I need help displaying data from the Steam API using a Flatlist in React Native我需要帮助在 React Native 中使用 Flatlist 显示来自 Steam API 的数据
【发布时间】:2019-12-16 19:46:59
【问题描述】:

我正在尝试在 React Native Flatlist 中显示来自 Steam API 的游戏信息。我是 React 和 JSX 的新手,所以我读到的很多内容都没有意义。

我希望平面列表显示特定帐户拥有的游戏名称列表。从 Steam 的 API 调用(通过 fetch)返回的数据如下所示:

{
"response": {
"game_count": 69,
"games": [
  {
    "appid": 220,
    "name": "Half-Life 2",
    "playtime_forever": 24,
    "img_icon_url": "fcfb366051782b8ebf2aa297f3b746395858cb62",
    "img_logo_url": "e4ad9cf1b7dc8475c1118625daf9abd4bdcbcad0",
    "has_community_visible_stats": true,
    "playtime_windows_forever": 0,
    "playtime_mac_forever": 0,
    "playtime_linux_forever": 0
  },
  {
    "appid": 320,
    "name": "Half-Life 2: Deathmatch",
    "playtime_forever": 0,
    "img_icon_url": "795e85364189511f4990861b578084deef086cb1",
    "img_logo_url": "6dd9f66771300f2252d411e50739a1ceae9e5b30",
    "has_community_visible_stats": true,
    "playtime_windows_forever": 0,
    "playtime_mac_forever": 0,
    "playtime_linux_forever": 0
  },

等等。因为我试图按名称显示游戏列表,所以 name 属性是我唯一需要的。

数据将每个游戏列为匿名对象,因此我无法像往常一样使用点符号访问每个游戏中的属性。我尝试使用 for 循环遍历它们,但这也不起作用。根据我的研究,似乎人们通常将 Array.map 用于此类事情,但我不清楚它是否可以与 Objects 一起使用。

我遇到的另一个问题是 Flatlist keyExtractor 属性。我知道它应该是一个匿名函数,它返回有关每个 Flatlist 项目的一些唯一索引或属性,目的是使结构更有效并允许它跟踪列表的更新。但是,我不知道如何自己创建此功能。我认为 JSON 数据中的 appid 字段将是一个不错的候选者,但我不确定如何将其放入 keyExtractor 函数中。

所以,把它作为一个问题:我将如何显示来自包含平面列表中匿名子对象的 JSON 对象的数据,以及如何使用不同的数据条目填充该列表的 keyExtractor (该列表中的appid

下面是我的起始代码:

import React, {Component} from 'react';
import {FlatList, Stylesheet, Text, View} from 'react-native';

export default class App extends Component {
  state = {
    dataset: []
  };

  componentWillMount() {
    this.fetchData();
  }

  fetchData = async () => {
    const response = await fetch("<API URL>");
    const json = await response.json();
    //const data = json.map((item) => item.games.name);
    var key = 0;
    const data = json[games][0][name];
    this.setState({ dataset: data });
  }

  render() {
      console.log(this.state.dataset);
    return (
      <View>
        <FlatList
          data={this.state.dataset}
          keyExtractor={(x, i) => i} //I have no idea what this does, or if it makes sense here.  
                                     //Where do x and i come from? (I got this from a tutorial video
                                     //and this was glossed over)

          renderItem={({ item }) => //Where does item come from?
            <Text>
              {item}
            </Text>
          }
        />
      </View>
    );
  }
}

【问题讨论】:

    标签: json react-native react-native-flatlist


    【解决方案1】:

    好的,您似乎在理解FlatList 的工作原理方面遇到了一些小问题。让我为你分解一下。

    让我们从 Steam API 请求开始。在您的示例中,您首先将 dataset 声明为您所在州的空数组,然后尝试使用网络请求的结果对其进行更新,这是要走的路。问题是,当您执行json['games'][0]['name'] 时,您正在访问games 数组的第一项(索引0)并获取它的name property,然后将该名称设置为您的dataset。尽管您忘记了属性名称的引号,但它不起作用。你需要做的是这样的:

    fetchAllGames = async () => {
        const steamResponse = await fetch("<API URL>");
        const json = await steamResponse.json();
    
        // We get all the games back from Steam in the form of an array
        this.setState({ games : json.games });
    }
    

    我们现在正在使用来自 games 数组的数据正确地更新状态中的数组。

    让我们继续讨论keyExtractorrenderItem 函数。 keyExtractor 函数用于告诉 React 每个列表项的唯一标识符。在这种情况下,这将是游戏的appid 属性。然后 React 使用这个唯一 ID 来区分项目并确定哪些项目需要更新。该函数为您提供两个参数,即实际项目及其索引。使用这些,我们可以执行以下操作:

    keyExtractor = (item, index) => {
        return item.appid.toString();
    }
    

    我们现在将 appid 属性作为字符串返回(这是 React 期望 key 的类型)。

    renderItem 函数有点不同,React 为您提供了一个参数,其中包含您的项目以及许多其他属性。由于我们只对实际项目感兴趣,因此我们使用如下括号对其进行解构:{ item }。这是 JavaScript 中常用的一种从对象中“提取”属性的技术。它通常是这样使用的:

    const testObj = {
        name : "John",
        surname : "Doe"
    }
    
    const { name, surname } = testObj; 
    

    这样,您可以直接引用namesurname,就好像它们是自变量一样。另一种方法是:

    const testObj = {
        name : "John",
        surname : "Doe"
    }
    
    const name = testObj.name;
    const surname = testObj.surname;
    

    我希望这能解决您可能一直在问自己的一些问题!下面是完整的工作代码。您可能会注意到我将一些内联函数移动到类成员中,这只是为了防止函数在每次渲染时重新创建的性能优化,您可以忽略它。

    import React, { Component } from 'react';
    import { FlatList, Text } from 'react-native';
    
    export default class App extends Component {
    
        state = {
            games : []
        };
    
        componentDidMount() {
            this.fetchAllGames();
        }
    
        fetchAllGames = async () => {
            const steamResponse = await fetch("<API URL>");
            const json = await steamResponse.json();
    
            // We get all the games back from Steam in the form of an array
            this.setState({ games : json.response.games });
        }
    
        keyExtractor = (item, index) => {
            return item.appid.toString();
        }
    
        renderItem = ({item}) => {
            return (
                <Text>{item.name}</Text>
            );
        }
    
        render() {
            return (
                <FlatList 
                    data={this.state.games}
                    keyExtractor={this.keyExtractor}
                    renderItem={this.renderItem} />
            );
        }
    }
    

    编辑 #1 - 正如 OP 所指出的,我犯了一个错字并更正了它。我还更改了 JSON 对象以反映 response 属性。

    【讨论】:

    • 非常感谢您的帮助以及您在此回复中投入的时间。 :)
    • 由于编辑限制,请跟进评论。我必须更改一些东西才能使代码正常工作。 renderItem=(this.renderItem) 变为 ={this.renderItem},(语法错误)。我必须处理从 Steam (let data = JSON.parse(JSON.stringify(json))) 获得的 JSON 对象。我还必须将setState 中的引用更改为data.response.games。 (对于将来阅读此内容的任何人,我从link 获得了有关 JSON 技巧的信息)
    • 修复错别字做得好!我在编辑中更正了您的两个观点。不过,我认为您不需要使用 JSON.parse(),这就是 steamResponse.json() 返回对象的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-02
    • 1970-01-01
    • 1970-01-01
    • 2010-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多