React Native - 无法在屏幕上呈现来自 API 的数据
React Native- Can't rendering data from API on the screen
在上一个屏幕上,您可以选择一集。在此屏幕上,剧集 ID 来自前一屏幕,使用此 ID,它从 API 中获取每个角色 ID。字符 ID 是从字符 URL 中截取的。您可以在剧集数据示例中查看详细信息。这个画面渲染的时候,没有报错,flatlist上也没有角色名。我该如何解决这个问题?
API: https://rickandmortyapi.com/api/
这里代码:
const EpisodeDetailScreen = (props) => {
const { styles, colors } = useThemedValues(getStyles);
const loc = useLocalization();
// character list for flatlist
const [characterList, setCharacterList] = useState([
{
"created": "",
"episode": [""],
"gender": "",
"id": 0,
"image": "",
"location": { "name": "", "url": "" },
"name": "",
"origin": { "name": "", "url": "" },
"species": "",
"status": "",
"type": "",
"url": ""
},
])
// episode details
const [episodeDetail, setEpisodeDetail] = useState([])
// this id come from previous screen
const { episodeId } = props.route.params
// details of a chosen episode from the previous screen
useEffect(() => {
Axios.get('episode/' + episodeId)
.then(response => {
let episodeDetail = response.data
setEpisodeDetail(episodeDetail) // episode details
//Getting the IDs of the characters in the section from the last part of the URLs in the incoming data
// You can see in data example that
for (var i = 0; i < episodeDetail.characters.length; i++) {
var charactersUrlInEpisode = episodeDetail.characters[i]
var charactersIdInUrl = charactersUrlInEpisode.slice(42, charactersUrlInEpisode.length)
// Extracting character ids and character details from API and throwing them into state
takeCharacters(charactersIdInUrl)
console.log(charactersIdInUrl) // I can see the correct IDs
}
})
.catch(error => {
console.log(error)
})
}, [])
// function that pulls character details from api based on given id
const takeCharacters = (id) => {
Axios.get('character/' + id)
.then(response => {
let characterDetail = response.data
setCharacterList(characterDetail)
console.log(characterDetail) // I can see characters data on console
})
.catch(error => {
console.log(error)
})
}
const _renderCharactersItem = ({ item }) => {
console.log('flatlist') // its working but flatList not rendering anything
return (
<TouchableOpacity onPress={() => {
props.navigation.navigate("character-detail-screen", {
characterId: item.id
});
}}>
<View style={styles.characterButton}>
<Text style={styles.characterNameText} numberOfLines={1}>{item.name}</Text>
</View>
</TouchableOpacity>
)
}
return (
<View style={styles.container}>
<View style={styles.episodeNameContainer}>
<Text style={styles.episodeNameText}>{episodeDetail.name}</Text>
</View>
<View style={styles.detailsContainer}>
<Text style={styles.detailsText}>{loc.t(texts.episode)}{episodeDetail.episode}</Text>
<Text style={styles.detailsText}>{loc.t(texts.airDate)} {episodeDetail.air_date}</Text>
</View>
<View style={styles.characterTitleContainer}>
<Text style={styles.characterTitleText}>{loc.t(texts.characters)}</Text>
</View>
<FlatList
data={characterList}
renderItem={_renderCharactersItem}
keyExtractor={item => item.id}
style={styles.flatListContainer}
/>
</View>
);
};
export default EpisodeDetailScreen;
剧集数据示例:
{
"id": 1,
"name": "Pilot",
"air_date": "December 2, 2013",
"episode": "S01E01",
"characters": [
"https://rickandmortyapi.com/api/character/1",
"https://rickandmortyapi.com/api/character/2",
"https://rickandmortyapi.com/api/character/35",
"https://rickandmortyapi.com/api/character/38",
"https://rickandmortyapi.com/api/character/62",
"https://rickandmortyapi.com/api/character/92",
"https://rickandmortyapi.com/api/character/127",
"https://rickandmortyapi.com/api/character/144",
"https://rickandmortyapi.com/api/character/158",
"https://rickandmortyapi.com/api/character/175",
"https://rickandmortyapi.com/api/character/179",
"https://rickandmortyapi.com/api/character/181",
"https://rickandmortyapi.com/api/character/239",
"https://rickandmortyapi.com/api/character/249",
"https://rickandmortyapi.com/api/character/271",
"https://rickandmortyapi.com/api/character/338",
"https://rickandmortyapi.com/api/character/394",
"https://rickandmortyapi.com/api/character/395",
"https://rickandmortyapi.com/api/character/435"
],
"url": "https://rickandmortyapi.com/api/episode/1",
"created": "2017-11-10T12:56:33.798Z"
}
字符数据示例:
{
"id": 1,
"name": "Rick Sanchez",
"status": "Alive",
"species": "Human",
"type": "",
"gender": "Male",
"origin": {
"name": "Earth (C-137)",
"url": "https://rickandmortyapi.com/api/location/1"
},
"location": {
"name": "Earth (Replacement Dimension)",
"url": "https://rickandmortyapi.com/api/location/20"
},
"image": "https://rickandmortyapi.com/api/character/avatar/1.jpeg",
"episode": [
"https://rickandmortyapi.com/api/episode/1",
"https://rickandmortyapi.com/api/episode/2",
"https://rickandmortyapi.com/api/episode/3",
"https://rickandmortyapi.com/api/episode/4",
"https://rickandmortyapi.com/api/episode/5",
"https://rickandmortyapi.com/api/episode/6",
"https://rickandmortyapi.com/api/episode/7",
"https://rickandmortyapi.com/api/episode/8",
"https://rickandmortyapi.com/api/episode/9",
"https://rickandmortyapi.com/api/episode/10",
"https://rickandmortyapi.com/api/episode/11",
"https://rickandmortyapi.com/api/episode/12",
"https://rickandmortyapi.com/api/episode/13",
"https://rickandmortyapi.com/api/episode/14",
"https://rickandmortyapi.com/api/episode/15",
"https://rickandmortyapi.com/api/episode/16",
"https://rickandmortyapi.com/api/episode/17",
"https://rickandmortyapi.com/api/episode/18",
"https://rickandmortyapi.com/api/episode/19",
"https://rickandmortyapi.com/api/episode/20",
"https://rickandmortyapi.com/api/episode/21",
"https://rickandmortyapi.com/api/episode/22",
"https://rickandmortyapi.com/api/episode/23",
"https://rickandmortyapi.com/api/episode/24",
"https://rickandmortyapi.com/api/episode/25",
"https://rickandmortyapi.com/api/episode/26",
"https://rickandmortyapi.com/api/episode/27",
"https://rickandmortyapi.com/api/episode/28",
"https://rickandmortyapi.com/api/episode/29",
"https://rickandmortyapi.com/api/episode/30",
"https://rickandmortyapi.com/api/episode/31",
"https://rickandmortyapi.com/api/episode/32",
"https://rickandmortyapi.com/api/episode/33",
"https://rickandmortyapi.com/api/episode/34",
"https://rickandmortyapi.com/api/episode/35",
"https://rickandmortyapi.com/api/episode/36",
"https://rickandmortyapi.com/api/episode/37",
"https://rickandmortyapi.com/api/episode/38",
"https://rickandmortyapi.com/api/episode/39",
"https://rickandmortyapi.com/api/episode/40",
"https://rickandmortyapi.com/api/episode/41"
],
"url": "https://rickandmortyapi.com/api/character/1",
"created": "2017-11-04T18:48:46.250Z"
}
当你调用端点'character/' + id
时,你得到的对象的形状是这个
{
"id": 1,
"name": "Rick Sanchez",
"status": "Alive",
"species": "Human",
"type": "",
"gender": "Male",
"origin": {
"name": "Earth (C-137)",
"url": "https://rickandmortyapi.com/api/location/1"
},
"location": {
"name": "Earth (Replacement Dimension)",
"url": "https://rickandmortyapi.com/api/location/20"
},
"image": "https://rickandmortyapi.com/api/character/avatar/1.jpeg",
"episode": [
"https://rickandmortyapi.com/api/episode/1",
"https://rickandmortyapi.com/api/episode/2",
"https://rickandmortyapi.com/api/episode/3",
"https://rickandmortyapi.com/api/episode/4",
"https://rickandmortyapi.com/api/episode/5",
"https://rickandmortyapi.com/api/episode/6",
"https://rickandmortyapi.com/api/episode/7",
"https://rickandmortyapi.com/api/episode/8",
"https://rickandmortyapi.com/api/episode/9",
"https://rickandmortyapi.com/api/episode/10",
"https://rickandmortyapi.com/api/episode/11",
"https://rickandmortyapi.com/api/episode/12",
"https://rickandmortyapi.com/api/episode/13",
"https://rickandmortyapi.com/api/episode/14",
"https://rickandmortyapi.com/api/episode/15",
"https://rickandmortyapi.com/api/episode/16",
"https://rickandmortyapi.com/api/episode/17",
"https://rickandmortyapi.com/api/episode/18",
"https://rickandmortyapi.com/api/episode/19",
"https://rickandmortyapi.com/api/episode/20",
"https://rickandmortyapi.com/api/episode/21",
"https://rickandmortyapi.com/api/episode/22",
"https://rickandmortyapi.com/api/episode/23",
"https://rickandmortyapi.com/api/episode/24",
"https://rickandmortyapi.com/api/episode/25",
"https://rickandmortyapi.com/api/episode/26",
"https://rickandmortyapi.com/api/episode/27",
"https://rickandmortyapi.com/api/episode/28",
"https://rickandmortyapi.com/api/episode/29",
"https://rickandmortyapi.com/api/episode/30",
"https://rickandmortyapi.com/api/episode/31",
"https://rickandmortyapi.com/api/episode/32",
"https://rickandmortyapi.com/api/episode/33",
"https://rickandmortyapi.com/api/episode/34",
"https://rickandmortyapi.com/api/episode/35",
"https://rickandmortyapi.com/api/episode/36",
"https://rickandmortyapi.com/api/episode/37",
"https://rickandmortyapi.com/api/episode/38",
"https://rickandmortyapi.com/api/episode/39",
"https://rickandmortyapi.com/api/episode/40",
"https://rickandmortyapi.com/api/episode/41"
],
"url": "https://rickandmortyapi.com/api/character/1",
"created": "2017-11-04T18:48:46.250Z"
}
如您所见,这不是一个数组,而是一个包含剧集数组的对象。
在你的函数 takeCharacters
中,你调用 setCharacterList(characterDetail)
,其中 characterDetail
是你的 api 的响应,我说过,它不是一个数组,这就是为什么你什么都看不到的原因(FlatList
想要一个数组来渲染)。
如果仔细查看 api 数据的形状,您会发现:
- 为您提供剧集列表的端点,其中每个剧集对象都包含一个字符列表,但您只有 link
- 为您提供有关单集信息的端点。
我建议你这样做(我没有测试它,但它应该有效,只是想建议你使用 Promise.all() 模式)
const promises = []
for (var i = 0;i < episodeDetail.characters.length;i++) {
var charactersUrlInEpisode = episodeDetail.characters[i]
var charactersIdInUrl = charactersUrlInEpisode.slice(42, charactersUrlInEpisode.length)
// Build a promise array to get the characters one by one
// takeCharacters(charactersIdInUrl)
promises.push(const promise = Axios.get('character/' + charactersIdInUrl);)
console.log(charactersIdInUrl) // I can see the correct IDs
}
Promise.all(promises)
.then((data) => {
// data should be an array that you can set as FlatList's data
console.log("fetched data", data);
})
PS:这与你的问题无关,但我建议更换这个
var charactersIdInUrl = charactersUrlInEpisode.slice(42, charactersUrlInEpisode.length)
有了这个
cost splittedUrl=charactersUrlInEpisode.split("/");
var charactersIdInUrl = splittedUrl[splittedUrl-length - 1]
它更可靠,因为它不依赖于 url 的长度
在上一个屏幕上,您可以选择一集。在此屏幕上,剧集 ID 来自前一屏幕,使用此 ID,它从 API 中获取每个角色 ID。字符 ID 是从字符 URL 中截取的。您可以在剧集数据示例中查看详细信息。这个画面渲染的时候,没有报错,flatlist上也没有角色名。我该如何解决这个问题?
API: https://rickandmortyapi.com/api/
这里代码:
const EpisodeDetailScreen = (props) => {
const { styles, colors } = useThemedValues(getStyles);
const loc = useLocalization();
// character list for flatlist
const [characterList, setCharacterList] = useState([
{
"created": "",
"episode": [""],
"gender": "",
"id": 0,
"image": "",
"location": { "name": "", "url": "" },
"name": "",
"origin": { "name": "", "url": "" },
"species": "",
"status": "",
"type": "",
"url": ""
},
])
// episode details
const [episodeDetail, setEpisodeDetail] = useState([])
// this id come from previous screen
const { episodeId } = props.route.params
// details of a chosen episode from the previous screen
useEffect(() => {
Axios.get('episode/' + episodeId)
.then(response => {
let episodeDetail = response.data
setEpisodeDetail(episodeDetail) // episode details
//Getting the IDs of the characters in the section from the last part of the URLs in the incoming data
// You can see in data example that
for (var i = 0; i < episodeDetail.characters.length; i++) {
var charactersUrlInEpisode = episodeDetail.characters[i]
var charactersIdInUrl = charactersUrlInEpisode.slice(42, charactersUrlInEpisode.length)
// Extracting character ids and character details from API and throwing them into state
takeCharacters(charactersIdInUrl)
console.log(charactersIdInUrl) // I can see the correct IDs
}
})
.catch(error => {
console.log(error)
})
}, [])
// function that pulls character details from api based on given id
const takeCharacters = (id) => {
Axios.get('character/' + id)
.then(response => {
let characterDetail = response.data
setCharacterList(characterDetail)
console.log(characterDetail) // I can see characters data on console
})
.catch(error => {
console.log(error)
})
}
const _renderCharactersItem = ({ item }) => {
console.log('flatlist') // its working but flatList not rendering anything
return (
<TouchableOpacity onPress={() => {
props.navigation.navigate("character-detail-screen", {
characterId: item.id
});
}}>
<View style={styles.characterButton}>
<Text style={styles.characterNameText} numberOfLines={1}>{item.name}</Text>
</View>
</TouchableOpacity>
)
}
return (
<View style={styles.container}>
<View style={styles.episodeNameContainer}>
<Text style={styles.episodeNameText}>{episodeDetail.name}</Text>
</View>
<View style={styles.detailsContainer}>
<Text style={styles.detailsText}>{loc.t(texts.episode)}{episodeDetail.episode}</Text>
<Text style={styles.detailsText}>{loc.t(texts.airDate)} {episodeDetail.air_date}</Text>
</View>
<View style={styles.characterTitleContainer}>
<Text style={styles.characterTitleText}>{loc.t(texts.characters)}</Text>
</View>
<FlatList
data={characterList}
renderItem={_renderCharactersItem}
keyExtractor={item => item.id}
style={styles.flatListContainer}
/>
</View>
);
};
export default EpisodeDetailScreen;
剧集数据示例:
{
"id": 1,
"name": "Pilot",
"air_date": "December 2, 2013",
"episode": "S01E01",
"characters": [
"https://rickandmortyapi.com/api/character/1",
"https://rickandmortyapi.com/api/character/2",
"https://rickandmortyapi.com/api/character/35",
"https://rickandmortyapi.com/api/character/38",
"https://rickandmortyapi.com/api/character/62",
"https://rickandmortyapi.com/api/character/92",
"https://rickandmortyapi.com/api/character/127",
"https://rickandmortyapi.com/api/character/144",
"https://rickandmortyapi.com/api/character/158",
"https://rickandmortyapi.com/api/character/175",
"https://rickandmortyapi.com/api/character/179",
"https://rickandmortyapi.com/api/character/181",
"https://rickandmortyapi.com/api/character/239",
"https://rickandmortyapi.com/api/character/249",
"https://rickandmortyapi.com/api/character/271",
"https://rickandmortyapi.com/api/character/338",
"https://rickandmortyapi.com/api/character/394",
"https://rickandmortyapi.com/api/character/395",
"https://rickandmortyapi.com/api/character/435"
],
"url": "https://rickandmortyapi.com/api/episode/1",
"created": "2017-11-10T12:56:33.798Z"
}
字符数据示例:
{
"id": 1,
"name": "Rick Sanchez",
"status": "Alive",
"species": "Human",
"type": "",
"gender": "Male",
"origin": {
"name": "Earth (C-137)",
"url": "https://rickandmortyapi.com/api/location/1"
},
"location": {
"name": "Earth (Replacement Dimension)",
"url": "https://rickandmortyapi.com/api/location/20"
},
"image": "https://rickandmortyapi.com/api/character/avatar/1.jpeg",
"episode": [
"https://rickandmortyapi.com/api/episode/1",
"https://rickandmortyapi.com/api/episode/2",
"https://rickandmortyapi.com/api/episode/3",
"https://rickandmortyapi.com/api/episode/4",
"https://rickandmortyapi.com/api/episode/5",
"https://rickandmortyapi.com/api/episode/6",
"https://rickandmortyapi.com/api/episode/7",
"https://rickandmortyapi.com/api/episode/8",
"https://rickandmortyapi.com/api/episode/9",
"https://rickandmortyapi.com/api/episode/10",
"https://rickandmortyapi.com/api/episode/11",
"https://rickandmortyapi.com/api/episode/12",
"https://rickandmortyapi.com/api/episode/13",
"https://rickandmortyapi.com/api/episode/14",
"https://rickandmortyapi.com/api/episode/15",
"https://rickandmortyapi.com/api/episode/16",
"https://rickandmortyapi.com/api/episode/17",
"https://rickandmortyapi.com/api/episode/18",
"https://rickandmortyapi.com/api/episode/19",
"https://rickandmortyapi.com/api/episode/20",
"https://rickandmortyapi.com/api/episode/21",
"https://rickandmortyapi.com/api/episode/22",
"https://rickandmortyapi.com/api/episode/23",
"https://rickandmortyapi.com/api/episode/24",
"https://rickandmortyapi.com/api/episode/25",
"https://rickandmortyapi.com/api/episode/26",
"https://rickandmortyapi.com/api/episode/27",
"https://rickandmortyapi.com/api/episode/28",
"https://rickandmortyapi.com/api/episode/29",
"https://rickandmortyapi.com/api/episode/30",
"https://rickandmortyapi.com/api/episode/31",
"https://rickandmortyapi.com/api/episode/32",
"https://rickandmortyapi.com/api/episode/33",
"https://rickandmortyapi.com/api/episode/34",
"https://rickandmortyapi.com/api/episode/35",
"https://rickandmortyapi.com/api/episode/36",
"https://rickandmortyapi.com/api/episode/37",
"https://rickandmortyapi.com/api/episode/38",
"https://rickandmortyapi.com/api/episode/39",
"https://rickandmortyapi.com/api/episode/40",
"https://rickandmortyapi.com/api/episode/41"
],
"url": "https://rickandmortyapi.com/api/character/1",
"created": "2017-11-04T18:48:46.250Z"
}
当你调用端点'character/' + id
时,你得到的对象的形状是这个
{
"id": 1,
"name": "Rick Sanchez",
"status": "Alive",
"species": "Human",
"type": "",
"gender": "Male",
"origin": {
"name": "Earth (C-137)",
"url": "https://rickandmortyapi.com/api/location/1"
},
"location": {
"name": "Earth (Replacement Dimension)",
"url": "https://rickandmortyapi.com/api/location/20"
},
"image": "https://rickandmortyapi.com/api/character/avatar/1.jpeg",
"episode": [
"https://rickandmortyapi.com/api/episode/1",
"https://rickandmortyapi.com/api/episode/2",
"https://rickandmortyapi.com/api/episode/3",
"https://rickandmortyapi.com/api/episode/4",
"https://rickandmortyapi.com/api/episode/5",
"https://rickandmortyapi.com/api/episode/6",
"https://rickandmortyapi.com/api/episode/7",
"https://rickandmortyapi.com/api/episode/8",
"https://rickandmortyapi.com/api/episode/9",
"https://rickandmortyapi.com/api/episode/10",
"https://rickandmortyapi.com/api/episode/11",
"https://rickandmortyapi.com/api/episode/12",
"https://rickandmortyapi.com/api/episode/13",
"https://rickandmortyapi.com/api/episode/14",
"https://rickandmortyapi.com/api/episode/15",
"https://rickandmortyapi.com/api/episode/16",
"https://rickandmortyapi.com/api/episode/17",
"https://rickandmortyapi.com/api/episode/18",
"https://rickandmortyapi.com/api/episode/19",
"https://rickandmortyapi.com/api/episode/20",
"https://rickandmortyapi.com/api/episode/21",
"https://rickandmortyapi.com/api/episode/22",
"https://rickandmortyapi.com/api/episode/23",
"https://rickandmortyapi.com/api/episode/24",
"https://rickandmortyapi.com/api/episode/25",
"https://rickandmortyapi.com/api/episode/26",
"https://rickandmortyapi.com/api/episode/27",
"https://rickandmortyapi.com/api/episode/28",
"https://rickandmortyapi.com/api/episode/29",
"https://rickandmortyapi.com/api/episode/30",
"https://rickandmortyapi.com/api/episode/31",
"https://rickandmortyapi.com/api/episode/32",
"https://rickandmortyapi.com/api/episode/33",
"https://rickandmortyapi.com/api/episode/34",
"https://rickandmortyapi.com/api/episode/35",
"https://rickandmortyapi.com/api/episode/36",
"https://rickandmortyapi.com/api/episode/37",
"https://rickandmortyapi.com/api/episode/38",
"https://rickandmortyapi.com/api/episode/39",
"https://rickandmortyapi.com/api/episode/40",
"https://rickandmortyapi.com/api/episode/41"
],
"url": "https://rickandmortyapi.com/api/character/1",
"created": "2017-11-04T18:48:46.250Z"
}
如您所见,这不是一个数组,而是一个包含剧集数组的对象。
在你的函数 takeCharacters
中,你调用 setCharacterList(characterDetail)
,其中 characterDetail
是你的 api 的响应,我说过,它不是一个数组,这就是为什么你什么都看不到的原因(FlatList
想要一个数组来渲染)。
如果仔细查看 api 数据的形状,您会发现:
- 为您提供剧集列表的端点,其中每个剧集对象都包含一个字符列表,但您只有 link
- 为您提供有关单集信息的端点。
我建议你这样做(我没有测试它,但它应该有效,只是想建议你使用 Promise.all() 模式)
const promises = []
for (var i = 0;i < episodeDetail.characters.length;i++) {
var charactersUrlInEpisode = episodeDetail.characters[i]
var charactersIdInUrl = charactersUrlInEpisode.slice(42, charactersUrlInEpisode.length)
// Build a promise array to get the characters one by one
// takeCharacters(charactersIdInUrl)
promises.push(const promise = Axios.get('character/' + charactersIdInUrl);)
console.log(charactersIdInUrl) // I can see the correct IDs
}
Promise.all(promises)
.then((data) => {
// data should be an array that you can set as FlatList's data
console.log("fetched data", data);
})
PS:这与你的问题无关,但我建议更换这个
var charactersIdInUrl = charactersUrlInEpisode.slice(42, charactersUrlInEpisode.length)
有了这个
cost splittedUrl=charactersUrlInEpisode.split("/");
var charactersIdInUrl = splittedUrl[splittedUrl-length - 1]
它更可靠,因为它不依赖于 url 的长度