[英]Why am I getting Object are not valid as a React child
I am using a Spotify API to fetch songs and I am trying to display the first song for testing.我正在使用 Spotify API 来获取歌曲,我正在尝试显示第一首歌曲进行测试。
I am trying to display the first song as text but currently I am getting the error "Objects are not valid as a React child (found: Object with keys {_U, _V, _W, _X}). If you meant to render a collection of children use a array instead.我正在尝试将第一首歌曲显示为文本,但目前我收到错误“对象作为 React 子项无效(找到:Object,键为 {_U、_V、_W、_X})。如果您打算渲染集合的孩子改用数组。
I am confused as I am just trying to the first thing from the JSON and display it as a text on the stats screen我很困惑,因为我只是想从 JSON 开始做第一件事,并将其显示为统计屏幕上的文本
import React, {useState} from "react";
import axios from "axios";
import { getSpotifyToken } from "../../hooks/spotifyAuth";
const getTopTracks = async () => {
//Getting spotify token
const spotifyToken = getSpotifyToken();
console.log("Getting access Token for TopSongs:", spotifyToken );
// const [songName, setSongName] = useState("");
const api_url = "https://api.spotify.com/v1/me/top/tracks?time_range=short_term&limit=5";
// const api_url = "https://api.spotify.com/v1/me/top/artists?time_range=short_term&limit=1&offset=5";
// console.log(api_url);
try{
const response = await axios.get(api_url, {
headers: {
'Authorization': `Bearer ${spotifyToken}`
}
});
const myJSON = response.data.items[0].name.toString();
console.log("My JSON:", myJSON); //this just prints the song name
return myJSON;
}catch(error){
console.log(error);
}
};
const StatsScreen = ({ navigation }) => {
const topSong = getTopTracks();
return (
<View>
<Text>StatsScreen</Text>
<Text>{topSong}</Text>
</View>
);
};
export default StatsScreen;
Because topSong
is a promise, not a string.因为
topSong
是 promise,而不是字符串。 async
functions always return promises ( more here ). async
函数总是返回承诺( 更多在这里)。
If you want StatsScreen
to retrieve the top song, you'll need to make it stateful, since initially it won't have a song to show:如果您希望
StatsScreen
检索热门歌曲,则需要使其有状态,因为最初它不会显示歌曲:
const StatsScreen = ({ navigation }) => {
const [topSong, setTopSong] = useState(null);
useEffect(() => {
getTopSongs()
.then(setTopSong)
.catch((error) => {
// ...handle/report error...
})
}, []); // <== Empty deps array = only on mount
return (
<View>
<Text>StatsScreen</Text>
{topSong && <Text>{topSong}</Text>}
</View>
);
};
That fetches the top song on mount via useEffect
, and stores the result as state using useState
.它通过
useEffect
获取 mount 上的第一首歌曲,并使用 useState 将结果存储为useState
。 I've had it not render the second Text
at all when it doesn't have one, but of course you can tweak that as desired, for instance:当它没有第二个文本时,我根本没有渲染第二个
Text
,但是当然您可以根据需要进行调整,例如:
return (
<View>
<Text>StatsScreen</Text>
<Text>{topSong ? topSong : "Loading top song..."}</Text>
</View>
);
};
A more robust version can use an AbortController
( in axios v0.22.0 and up ; for earlier versions, use the deprecated axios-specific CancelToken
) to cancel the outstanding HTTP request if the component is unmounted while it's running:更健壮的版本可以使用
AbortController
(在 axios v0.22.0 及更高版本中;对于早期版本,使用已弃用的 axios 特定的CancelToken
)来取消未完成的 HTTP 请求,如果组件在运行时被卸载:
const getTopTracks = async (signal) => {
// ^^^^^^ <====
// ...
try {
const response = await axios.get(api_url, {
signal, // <====
headers: {
Authorization: `Bearer ${spotifyToken}`,
},
});
// ...
} catch (error) {
console.log(error);
}
};
const StatsScreen = ({ navigation }) => {
const [topSong, setTopSong] = useState(null);
useEffect(() => {
const controller = new AbortController(); // <====
getTopSongs(controller.signal) // <====
.then(setTopSong)
.catch((error) => {
// ...handle/report error...
});
return () => { // <====
// Called on unmount // <====
controller.abort(); // <====
};
}, []); // <== Empty deps array = only on mount
return (
<View>
<Text>StatsScreen</Text>
{topSong && <Text>{topSong}</Text>}
</View>
);
};
Your getTopTracks()
is returning a promise as you have not await-ed the function call.您的
getTopTracks()
正在返回 promise 因为您尚未等待 function 调用。 Also you haven't called the API at the right place.此外,您还没有在正确的位置调用 API。
API calls are asynchronous and so the data comes after the component has rendered. API 调用是异步的,因此数据是在组件渲染之后出现的。 So the basic flow for any API call like this has to be:
因此,任何像这样的 API 调用的基本流程必须是:
Make a state variable to store the data.创建一个 state 变量来存储数据。
const [topSong, setTopSong] = useState("");
Call the API in a useEffect
(If the data is to be fetched only once, you may use an empty dependency array)在 useEffect 中调用
useEffect
(如果数据只获取一次,可以使用空的依赖数组)
useEffect(() => { const fetchTopSong = async () => { const response = await axios.get(...); setTopSong(response.data.items[0].name); } fetchTopSong(); }, []);
Use this state in your render method now.现在在您的渲染方法中使用这个 state。
return ( <View> <Text>StatsScreen</Text> <Text>{topSong}</Text> </View> );
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.