You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native调用Spotify API获取用户播放列表时出现未处理Promise拒绝错误的技术求助

问题排查与修复方案

咱们一步步拆解你遇到的问题,逐个解决:

1. 第一个错误:TypeError: undefined is not an object (evaluating 'data.items.name.map')

看Spotify返回的数据结构,items是一个数组,里面每个元素才是包含name属性的播放列表对象。你错误地尝试访问items.name(数组本身没有name属性,所以这个值是undefined),然后对undefined调用map,自然会触发报错。

正确的做法是直接遍历data.items数组,每个元素就是单个播放列表对象:

// 错误写法
data.items.name.map(obj => result.push({title: [obj.name]}));

// 正确写法
const result = data.items.map(obj => ({ title: obj.name }));

另外,没必要把name放进数组里,直接存字符串就行,后续渲染也会更简单。

2. 第二个错误:TypeError: undefined is not an object (evaluating 'item.title[1]')

你创建的result里每个元素的title是[obj.name](一个只有1个元素的数组),但渲染时你用了item.title[1]——数组索引从0开始,这里应该用item.title[0],或者更合理的是直接把title设为字符串,这样渲染时直接用item.title即可。

3. 潜在问题:Token的异步获取与初始状态

  • 你的token初始值是空字符串,而且getData是异步函数,用户可能在token还没从AsyncStorage取出来时就点击按钮,导致API调用的Authorization头无效。可以加个加载状态,或者在按钮点击时先检查token是否存在。
  • data的初始值是{},但FlatList需要数组类型的数据源,初始应该设为[],避免初始渲染时FlatList报错。

修复后的完整代码

import React, { useState, useEffect } from 'react';
import { View, Text, Button, FlatList, StyleSheet } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useTheme } from '@react-navigation/native';

export default function SpotifyGetPlaylist() { 
  const { colors } = useTheme(); 
  const [token, setToken] = useState(''); 
  const [data, setData] = useState([]); // 初始设为空数组
  const [isLoadingToken, setIsLoadingToken] = useState(true); // 新增加载状态

  useEffect(() => { 
    const fetchToken = async () => {
      const storedToken = await AsyncStorage.getItem('@access_token');
      setToken(storedToken || '');
      setIsLoadingToken(false);
    };
    fetchToken(); 
  }, []); 

  const playlistSearchApi = 'https://api.spotify.com/v1/me/playlists'; 

  const handleGetPlaylists = async () => { 
    if (!token) {
      console.log('Token not available yet');
      return;
    }

    try {
      const res = await fetch(playlistSearchApi, { 
        method: 'GET', 
        headers: { 
          'Authorization': `Bearer ${token}` 
        } 
      });
      const responseData = await res.json();
      
      // 处理返回的播放列表数据
      const result = responseData.items.map(obj => ({ 
        title: obj.name,
        id: obj.id // 用id作为key更可靠
      }));
      setData(result);
    } catch (error) {
      console.error('Failed to fetch playlists:', error);
    }
  } 

  const renderItem = ({item}) => { 
    return( 
      <View style={styles.item}> 
        <Text style={styles.playlistname}>{item.title}</Text> 
      </View> 
    ); 
  } 

  return ( 
    <View style={styles.container}> 
      <Button 
        onPress={handleGetPlaylists} 
        color="#1DB954" 
        style={{ width: 100 }} 
        title="Get your playlists"
        disabled={isLoadingToken || !token} // 加载中或无token时禁用按钮
      /> 
      <FlatList 
        data={data} 
        renderItem={renderItem} 
        keyExtractor={item => item.id} // 用播放列表的id作为key,更稳定
      /> 
    </View> 
  ) 
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
  },
  item: {
    padding: 12,
    borderBottomWidth: 1,
    borderBottomColor: '#eee',
  },
  playlistname: {
    fontSize: 16,
  },
});

额外优化点

  • 改用async/await替代then链,代码更易读也更易处理错误
  • 新增了错误捕获,避免未处理的Promise rejection
  • 用播放列表的id作为keyExtractor的值,比用title更可靠(避免重名播放列表的key冲突)
  • 添加了按钮禁用逻辑,防止在token未就绪时发起无效请求

内容的提问来源于stack exchange,提问作者MaxCode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 20:12:43