Possible Unhandled promise rejection TypeError: Network request failed, cannot read property 'map' of undefined

Viewed 27

Recently started learning react-native and I'm following this tutorial on youtube, I'm trying to fetch flags and country codes from some websites api but I'm getting an error saying

Possible Unhandled promise rejection TypeError: Network request failed, cannot read property 'map' of undefined

import {
    View,
    Text,
    TouchableOpacity,
    TouchableNativeFeedback,
    Image,
    TextInput,
    Modal,
    FlatList,
    KeyboardAvoidingView,
    ScrollView
} from "react-native";
import React from "react";
import LinearGradient from "react-native-linear-gradient";

import { COLORS, SIZES, FONTS, icons, images } from "../constants"

const SignUp = () => {

    const [showPassword, setShowPassword] = React.useState(false);

    const [areas, setAreas] = React.useState([]);
    const [selectedArea, setSelectedArea] = React.useState(null);
    const [modalVisible, setModalVisible] = React.useState(false);

    React.useEffect(() => {
        fetch("https://restcountries.eu/rest/v3.1/all")
            .then(response => response.json())
            .catch(err => {
                console.log(err);
            })
            .then((data) => {
                let areaData = data.map(item => {
                    return {
                        code: item.alpha2Code,
                        name: item.name,
                        callingCode: `+${item.callingCodes[0]}`,
                        flag: `https://countryflagsapi.com/png/${item.alpha2code}`
                    }
                }).catch(err => {
                    console.log(err);
                });

                setAreas(areaData)

                if (areaData.length > 0) {
                    let defaultData = areaData.filter(a => a.code == "US")

                    if (defaultData.length > 0) {
                        setSelectedArea(defaultData[0])
                    }
                }
            })
    }, [])

    function renderHeader() {
        return (
            <TouchableOpacity
                style={{
                    flexDirection: "row",
                    alignItems: "center",
                    marginTop: SIZES.padding * 2,
                    paddingHorizontal: SIZES.padding * 2
                }}
                onPress={() => console.log("SignUp")}
            >
                <Image
                    source={icons.back}
                    resizeMode="contain"
                    style={{
                        width: 20,
                        height: 20,
                        tintColor: COLORS.white
                    }}
                />

                <Text
                    style={{ marginLeft: SIZES.padding * 1.5, color: COLORS.white, ...FONTS.h4 }}
                >Sign Up</Text>
            </TouchableOpacity>
        )
    }

    function renderLogo() {
        return (
            <View
                style={{
                    marginTop: SIZES.padding * 5,
                    height: 100,
                    alignItems: 'center',
                    justifyContent: 'center'
                }}
            >
                <Image
                    source={images.wallieLogo}
                    resizeMode="contain"
                    style={{
                        width: "60%"
                    }}
                />
            </View>
        )
    }

    function renderForm() {
        return (
            <View
                style={{
                    marginTop: SIZES.padding * 3,
                    marginHorizontal: SIZES.padding * 3,
                }}
            >
                {/* Full Name */}
                <View
                    style={{
                        marginTop: SIZES.padding * 3,
                    }}
                >
                    <Text
                        style={{
                            color: COLORS.lightGreen, ...FONTS.body3
                        }}
                    >Full Name</Text>
                    <TextInput
                        style={{
                            marginVertical: SIZES.padding,
                            borderBottomColor: COLORS.white,
                            borderBottomWidth: 1,
                            height: 40,
                            color: COLORS.white,
                            ...FONTS.body3
                        }}
                        placeholder="Enter Full Name"
                        placeholderTextColor={COLORS.white}
                        selectionColor={COLORS.white}
                    />

                    {/* Phone Number */}
                    <View style={{ marginTop: SIZES.padding * 2 }}>
                        <Text style={{ color: COLORS.lightGreen, ...FONTS.body3 }}>Phone Number</Text>

                        <View style={{ flexDirection: "row" }}>
                            {/* Country Code */}
                            <TouchableOpacity
                                style={{
                                    width: 100,
                                    height: 50,
                                    marginHorizontal: 5,
                                    borderBottomColor: COLORS.white,
                                    borderBottomWidth: 1,
                                    flexDirection: "row",
                                    ...FONTS.body2
                                }}
                                onPress={() => console.log("Show Modal")}
                            >
                                <View style={{ justifyContent: "center" }}>
                                    <Image
                                        source={icons.down}
                                        style={{
                                            width: 10,
                                            height: 10,
                                            tintColor: COLORS.white,
                                        }}
                                    />
                                </View>
                                <View style={{ justifyContent: "center", marginLeft: 7 }}>
                                    <Image
                                        source={{ uri: selectedArea?.flag }}
                                        resizeMode="contain"
                                        style={{
                                            width: 30,
                                            height: 30
                                        }}
                                    />
                                </View>
                                <View style={{ justifyContent: "center", marginLeft: 7 }}>
                                    <Text style={{ color: COLORS.white, ...FONTS.body3 }}>{selectedArea?.callingCode}</Text>
                                </View>
                            </TouchableOpacity>

                            {/* Phone Number Input */}
                            <TextInput
                                style={{
                                    flex: 1,
                                    marginVertical: SIZES.padding,
                                    borderBottomColor: COLORS.white,
                                    borderBottomWidth: 1,
                                    height: 40,
                                    color: COLORS.white,
                                    ...FONTS.body3
                                }}
                                placeholder="Enter Phone Number"
                                placeholderTextColor={COLORS.white}
                                selectionColor={COLORS.white}
                            />
                        </View>
                    </View>

                    {/* Password */}
                    <View style={{ marginTop: SIZES.padding * 2 }}>
                        <Text
                            style={{
                                color: COLORS.lightGreen,
                                ...FONTS.body3
                            }}
                        >Password</Text>
                        <TextInput
                            style={{
                                marginVertical: SIZES.padding,
                                borderBottomColor: COLORS.white,
                                borderBottomWidth: 1,
                                height: 40,
                                color: COLORS.white,
                                ...FONTS.body3
                            }}
                            placeholder="Enter Password"
                            placeholderTextColor={COLORS.white}
                            selectionColor={COLORS.white}
                            secureTextEntry={!showPassword}
                        />
                        <TouchableOpacity
                            style={{
                                position: "absolute",
                                right: 0,
                                bottom: 10,
                                height: 30,
                                width: 30
                            }}
                            onPress={() => setShowPassword(!showPassword)}
                        >
                            <Image
                                source={showPassword ? icons.disable_eye : icons.eye}
                                style={{
                                    height: 20,
                                    width: 20,
                                    tintColor: COLORS.white
                                }}
                            />
                        </TouchableOpacity>
                    </View>
                </View>
            </View>
        )
    }

    function renderButton() {
        return (
            <View style={{ margin: SIZES.padding * 3 }}>
                <TouchableOpacity
                    style={{
                        height: 60,
                        backgroundColor: COLORS.black,
                        borderRadius: SIZES.radius / 1.5,
                        alignItems: "center",
                        justifyContent: "center"
                    }}
                    onPress={() => console.log("Let's Go")}
                >
                    <Text style={{ color: COLORS.white, ...FONTS.h3 }}>Continue</Text>
                </TouchableOpacity>

            </View>
        )
    }

    return (
        <KeyboardAvoidingView
            behavior={Platform.OS === "ios" ? "padding" : null}
            style={{ flex: 1 }}
        >
            <LinearGradient
                colors={[COLORS.lime, COLORS.emerald]}
                style={{ flex: 1 }}
            >
                <ScrollView>
                    {renderHeader()}
                    {renderLogo()}
                    {renderForm()}
                    {renderButton()}
                </ScrollView>
            </LinearGradient>
        </KeyboardAvoidingView>
    )
}

export default SignUp;

Saw an old post regarding this issue but the solution of adding catch(err didn't work please any suggestions

1 Answers

The problem you faced mainly occurs in the fetch() inside useEffect().

To handle the any potential errors in function, we will use catch() as @caslawter mentioned.

fetch("https://restcountries.eu/rest/v3.1/all")
.then(response => response.json())
.then((data) => {
    //... Do what you want after fetch data
})
.catch(err => {
    //Any error occurs in json parsing or after fetching data will jump to here
    console.log(err);
})

Also, please make sure your data is not undefined before you apply 'map' function to it.

Related