React Native - отображение данных полученных по API вызывает ошибку

Доброе утро!

Прошу помощи - глобально не понимаю проблемы в своём коде, только изучаю React Native.

Имеется вот такой код экрана

import React, {useEffect, useState} from 'react';
import { View, Text, Image, StyleSheet, TouchableOpacity, ScrollView, Alert } from 'react-native';
import { useNavigation} from '@react-navigation/native';
import AsyncStorage from '@react-native-async-storage/async-storage'

import NavigationButtons from "../Components/NavigationButtons";

//Объект данных
type ScreenData = {
    user:{
        user_id: string;
        user_name: string;
    },  
    balances: {
        balance: {
            balance: string;
            currency: string;
        },
        frozen: {
            balance: string;
            currency: string;
        },
        available: {
            balance: string;
            currency: string;
        }
    }
}

//Базовый шаблон экрана
const BalanceScreen = () => {

    const navigation = useNavigation();

    const [androidKey, setAndroidKey] = useState();    
    const [screenData, setScreenData] = useState<ScreenData>([]);
        
    //Проверка хранилища на наличие ключа
    //Подгрузка ключа
    const loadKeyData = async () => {
        try 
        {
            const value = await AsyncStorage.getItem('android_app_connect_key');
            
            if(value !== null) 
            {        
                setAndroidKey(value);    
                  
            }        
        } 
        catch (e) 
        {      
            //error
        }        
    };
    
    loadKeyData();

    const loadBalanceData = async () => {
        try 
        {
            if(androidTraderKey == null || androidTraderKey == '' || androidTraderKey == false)
            {
                return;                
            }
            const response = await fetch('here_external_url', {
                    method: 'POST',
                    headers: {
                        Accept: 'application/json',
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        android_app_connect_key: androidKey
                    }),
                });      
    
            const json = await response.json();                
            setScreenData(json);            
        } 
        catch (error) 
        {
            //error
        } 
        finally 
        {
            //finally
        }
    };

    loadBalanceData();

    return (

    <View style={styles.screen_wrapper}>        

        <ScrollView
            style={styles.screen_view}
        >    

            <View style={styles.user_data_head}>        
                <Text style={styles.user_data_head_title}>{screenData.user.user_name} #{screenData.user.user_id}</Text>
            </View>
        
        </ScrollView>
        
        <NavigationButtons />
        
    </View>
  );
};

export default BalanceScreen 

const styles = StyleSheet.create({

    screen_wrapper: {
        width: "100%",
        flex: 1,         
        backgroundColor: '#16171B',        
    },
    screen_view: {
        padding: 16,
    },
    screen_title: {
        fontFamily: 'Inter-SemiBold',
        fontSize: 16,
        color: "#ffffff",
        padding: 16,
    },

    user_data_head:{
        width: "100%",
        flex: 1,         
        justifyContent: 'flex-start',
        alignItems: 'flex-start',
        backgroundColor: '#1E1F28',
        borderRadius: 4,
        marginBottom: 4,
    },
    user_data_head_title:{
        fontFamily: 'Inter-Bold',
        fontSize: 16,
        color: "#ffffff",
        padding: 16,
    },

    user_data_balance_block:{
        width: "100%",
        flex: 1,
        flexDirection: 'column',
        justifyContent: 'flex-start',
        alignItems: 'flex-start',
        backgroundColor: '#1E1F28',
        borderRadius: 4,
        padding: 16,
        marginBottom: 4,
    },
    user_data_balance_block_title:{
        fontFamily: 'Inter-Regular',
        fontSize: 14,
        color: "#60667C",
        
    },
    user_data_balance_block_text:{
        fontFamily: 'Inter-SemiBold',
        fontSize: 16,
        color: "#ffffff",        
    }

});

Но в итоге получаю ошибку Cannot read property 'user_name' of undefined

Ответ АПИ при этом корректный

{
    "user": {
        "user_id": 844,
        "user_name": "testuser"
    },
    "balances": {
        "balance": {
            "currency": "rub",
            "balance": 569.87
        },
        "frozen": {
            "currency": "rub",
            "balance": 0
        },
        "available": {
            "currency": "rub",
            "balance": 569.87
        }
    }
}

Предполагаю, что ошибка возникает из-за отсутствия данных от АПИ в момент отрисовки/рендера экрана, но как победить проблему - ума не приложу.

UPD в useState добавил значения по-умолчанию

const [screenData, setScreenData] = useState<ScreenData>(
        {
            user: {
                user_name: 'none',
                user_id: 'none',
            },
            balances: {
                balance: 
                {
                    balance: '0',
                    currency: 'rub',
                },
                frozen: 
                {
                    balance: '0',
                    currency: 'rub',
                },
                available: 
                {
                    balance: '0',
                    currency: 'rub',
                }
            }            
        }
    );

и завязал всё это на useEffect

useEffect(() => {        
        loadBalanceData();
    }, [androidKey])

То есть, теперь пока не прогрузится androidKey запрос к АПИ не уходит.

Выглядит разумно и вроде как верно, мастера-js, что скажете?


Ответы (0 шт):