Reputation: 787
On the previous screen, you can choose an episode. On this screen, episode ID coming from the previous screen and with this ID, its taking every character ID from API. Characters IDs are slicing from characters URLs. The problem is flatList rendering all of the characters in one row (in one button) repeatedly and stopping at the character that has the last id. How can I solve that?
Episode API: https://rickandmortyapi.com/api/episode/ Character 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;
FlatList style:
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;
Upvotes: 0
Views: 826
Reputation: 602
You are replacing your charactersList
on every iteration. You must do like this
// 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)
})
}
You got it? Please, if this code does not correct your problem, provide some prints of your screen.
Upvotes: 2