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
相关产品推荐
相关产品推荐

