React Native - FlatList 重复渲染一行中的所有项目
React Native - FlatList rendering all of the items in one row repeatedly
在上一个屏幕上,您可以选择一集。在此屏幕上,剧集 ID 来自前一屏幕,使用此 ID,它从 API 中获取每个角色 ID。字符 ID 是从字符 URL 中截取的。问题是 flatList 重复渲染一行(在一个按钮中)的所有字符并停止在具有最后一个 id 的字符处。我该如何解决?
第 API 集:https://rickandmortyapi.com/api/episode/
字符API:https://rickandmortyapi.com/api/character/
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++) {
const charactersUrlInEpisode = episodeDetail.characters[i]
const splittedUrl = charactersUrlInEpisode.split("/");
const charactersIdInUrl = splittedUrl[splittedUrl.length - 1]
// Extracting character ids and character details from API and throwing them into state
takeCharacters(charactersIdInUrl)
console.log(charactersIdInUrl)
}
})
.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])
})
.catch(error => {
console.log(error)
})
}
const _renderCharactersItem = ({ item }) => {
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;
平面列表样式:
import { StyleSheet } from 'react-native';
import { colorNames } from '../../Theming'
import {Metrics, Fonts} from '../../../StylingConstants'
const styles = (Colors) => StyleSheet.create({
flatListContainer: {
flex:1,
paddingHorizontal: Metrics.width * 0.05
},
characterButton:{
justifyContent:'center',
alignItems:'center',
backgroundColor: Colors[colorNames.home.buttonBackground],
marginTop: Metrics.width / 24,
borderWidth: Metrics.width / 72,
borderRadius: Metrics.width / 20,
borderColor: Colors[colorNames.home.buttonBorder]
},
characterNameText:{
color: Colors[colorNames.home.episodeText],
fontSize: Fonts.size(18),
fontFamily: Fonts.type.bold,
marginHorizontal: Metrics.width * 0.05,
marginTop: Metrics.width / 36,
marginBottom: Metrics.width / 30
},
});
export default styles;
您将在每次迭代时替换您的 charactersList
。你必须这样做
// 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(previousState => [...previousState,...characterDetail])
})
.catch(error => {
console.log(error)
})
}
你明白了吗?如果此代码无法解决您的问题,请提供您的屏幕截图。
在上一个屏幕上,您可以选择一集。在此屏幕上,剧集 ID 来自前一屏幕,使用此 ID,它从 API 中获取每个角色 ID。字符 ID 是从字符 URL 中截取的。问题是 flatList 重复渲染一行(在一个按钮中)的所有字符并停止在具有最后一个 id 的字符处。我该如何解决?
第 API 集:https://rickandmortyapi.com/api/episode/ 字符API:https://rickandmortyapi.com/api/character/
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++) {
const charactersUrlInEpisode = episodeDetail.characters[i]
const splittedUrl = charactersUrlInEpisode.split("/");
const charactersIdInUrl = splittedUrl[splittedUrl.length - 1]
// Extracting character ids and character details from API and throwing them into state
takeCharacters(charactersIdInUrl)
console.log(charactersIdInUrl)
}
})
.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])
})
.catch(error => {
console.log(error)
})
}
const _renderCharactersItem = ({ item }) => {
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;
平面列表样式:
import { StyleSheet } from 'react-native';
import { colorNames } from '../../Theming'
import {Metrics, Fonts} from '../../../StylingConstants'
const styles = (Colors) => StyleSheet.create({
flatListContainer: {
flex:1,
paddingHorizontal: Metrics.width * 0.05
},
characterButton:{
justifyContent:'center',
alignItems:'center',
backgroundColor: Colors[colorNames.home.buttonBackground],
marginTop: Metrics.width / 24,
borderWidth: Metrics.width / 72,
borderRadius: Metrics.width / 20,
borderColor: Colors[colorNames.home.buttonBorder]
},
characterNameText:{
color: Colors[colorNames.home.episodeText],
fontSize: Fonts.size(18),
fontFamily: Fonts.type.bold,
marginHorizontal: Metrics.width * 0.05,
marginTop: Metrics.width / 36,
marginBottom: Metrics.width / 30
},
});
export default styles;
您将在每次迭代时替换您的 charactersList
。你必须这样做
// 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(previousState => [...previousState,...characterDetail])
})
.catch(error => {
console.log(error)
})
}
你明白了吗?如果此代码无法解决您的问题,请提供您的屏幕截图。