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)
            })
    }

你明白了吗?如果此代码无法解决您的问题,请提供您的屏幕截图。