JIT
adding scene skeleton for data loading in react native app
import React, {useState, useEffect, useCallback} from 'react'; import { TouchableOpacity, Text, View, FlatList, Alert, ActivityIndicator, } from 'react-native'; import {useUser} from '../../context/UserContext'; import ApiManager from '../../services/ApiManager'; import SceneSceenStyle from '../../styles/SceneSceenStyle'; import {useMqtt} from '../../context/MqttContext'; import {useFocusEffect} from '@react-navigation/native'; import {COLORS} from '../../styles/colors'; import uiStyle from '../../styles/uiStyle'; import SceneSkeleton from '../../services/SceneSkeleton'; const SceneScreen = ({navigation}) => { const [items, setItems] = useState([]); const [isFetching, setIsFetching] = useState(false); const {userDetails} = useUser(); const {connectionState, subscribe, unsubscribe, publish} = useMqtt(); // --- MQTT Topics --- const MQTT_SUBSCRIBE_TOPIC = 'advaint/cus_' + userDetails.customer_id + '/scene/feedback'; const MQTT_PUBLISH_TOPIC = 'advaint/cus_' + userDetails.customer_id + '/scene'; useEffect(() => { if (userDetails?.customer_id) { getSceneDetails(); } else { setItems([]); } }, [userDetails?.customer_id]); useFocusEffect( useCallback(() => { console.log( 'HomeScreen focused, subscribing to MQTT topic:', MQTT_SUBSCRIBE_TOPIC, ); const callback = (data, topic) => { // Handle incoming messages console.log(`Received MQTT message on topic: ${topic}, data: ${data}`); try { const payload = JSON.parse(data); console.log('Parsed MQTT Payload:', payload); if (payload && payload.scene_id && payload.scene_status) { setItems(prevItems => { return prevItems.map(item => { if (item.scene_id === payload.scene_id) { return {...item, scene_status: payload.scene_status}; } return item; }); }); } } catch (e) { console.warn('MQTT message data is not JSON:', data); } }; subscribe(MQTT_SUBSCRIBE_TOPIC, callback); return () => { console.log( 'HomeScreen blurred, unsubscribing from MQTT topic:', MQTT_SUBSCRIBE_TOPIC, ); unsubscribe(MQTT_SUBSCRIBE_TOPIC, callback); }; }, [subscribe, unsubscribe, userDetails?.flat]), ); const getSceneDetails = async (isManualRefresh = false) => { if (!userDetails?.customer_id) { console.log('User details not available yet or missing customer_id.'); setIsFetching(false); return; } console.log(`Fetching list... Manual Refresh: ${isManualRefresh}`); setIsFetching(true); const customer_id = userDetails.customer_id; try { const listResponse = await ApiManager.getScene(customer_id); console.log('zone received listResponse:', listResponse.Data); if (listResponse) { setItems(listResponse.Data); } else { console.error( 'API did not return expected data structure:', listResponse, ); setItems([]); if (isManualRefresh) { Alert.alert( 'Error', 'Failed to fetch items. Invalid data format received.', ); } } } catch (error) { console.error('Fetch List Error in CommunityScreen:', error); if (isManualRefresh) { Alert.alert( 'Fetch Failed', error.message || 'An unexpected error occurred while fetching items.', ); } setItems([]); } finally { setIsFetching(false); } }; const handleRefresh = () => { getSceneDetails(true); }; const changeScene = item => { console.log('item', item); const scenJson = { scene_id: item.scene_id, parameter: item.scene_status === 'ON' ? 0 : 1, mode: 'MOBILE', contact_id: userDetails.flat_contact_id, }; console.log('Publishing MQTT message:', scenJson); publish(MQTT_PUBLISH_TOPIC, scenJson); }; const renderItem = ({item}) => ( <TouchableOpacity style={[ SceneSceenStyle.zoneListView, { backgroundColor: item.scene_status === 'ON' ? uiStyle.blue_color : COLORS.white_color, }, ]} onPress={() => { changeScene(item); }}> <Text style={[ SceneSceenStyle.itemTypeText, {color: item.scene_status === 'ON' ? COLORS.white_color : null}, ]}> {item.scene_name} </Text> </TouchableOpacity> ); const renderContent = () => { if (isFetching && items.length === 0) { return <SceneSkeleton />; } if (!isFetching && items.length === 0) { return ( <View style={SceneSceenStyle.centeredMessageContainer}> <Text style={SceneSceenStyle.messageText}>No scene items found.</Text> </View> ); } return ( <FlatList data={items} renderItem={renderItem} keyExtractor={item => item.scene_id.toString()} contentContainerStyle={SceneSceenStyle.listContentContainer} onRefresh={handleRefresh} refreshing={isFetching} /> ); }; return <View style={SceneSceenStyle.safeArea}>{renderContent()}</View>; }; export default SceneScreen; i have used SceneSkeleton when data is loading on refresh also I want to fech SceneSkeleton untill data reloads make chnages and provide code with src folder
Updated files
v1