I am fetching data from an API that has a JSON file, I am trying to pass the data from app to appstack to sessionsStack that will then bring the data to the home page, currently my console.logs are telling me that my data is only getting to the appStack.
App
import {AppStack} from '#miniclementine:navigation/AppStack';
import Colors from '#miniclementine:common/appearance/Colors';
const DATA = "https://cg0wsrc3ue.execute-api.us-east-1.amazonaws.com/dev/getSessions"
const App: () => React$Node = () => {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
useEffect(() => {
fetch(DATA)
.then((response) => response.json())
.then((json) => setData(json.sessions))
.catch((error) => console.error(error))
.finally(() => setLoading(false));
console.log("the data: ", data)
}, []);
return (
<SafeAreaView style={styles.container}>
{ isLoading ? <ActivityIndicator /> : <AppStack data={data}/> }
</SafeAreaView>
);
};
App Stack
const Tab = createBottomTabNavigator();
export const AppStack = ({data}) => {
console.log("data in appstack", data)
return (
<NavigationContainer>
<Tab.Navigator tabBar={(props) => <MiniClementineTabBar {...props} />}>
<Tab.Screen name="Sessions" component={SessionsStack} data={data} />
<Tab.Screen name="Mantras" component={MantraStack} />
</Tab.Navigator>
</NavigationContainer>
);
};
Sessions Stack
import {createStackNavigator} from '#react-navigation/stack';
import SessionsHomepage from '#miniclementine:modules/sessions/SessionsHomepage';
import SessionsListPage from '#miniclementine:modules/sessions/SessionsListPage';
export const SESSIONS_HOMEPAGE = 'SESSIONS_HOMEPAGE';
export const SESSIONS_LIST_PAGE = 'SESSIONS_LIST_PAGE';
const Stack = createStackNavigator();
export default function SessionsStack({data}) {
console.log("data in SessionStack", data)
return (
<Stack.Navigator
screenOptions={{
headerShown: false,
}}>
<Stack.Screen name={'SESSIONS_HOMEPAGE'} component={SessionsHomepage} data={data} />
<Stack.Screen name={'SESSIONS_LIST_PAGE'} component={SessionsListPage} data={data} />
{/* #TODO: The two additional screens you need to create will be defined here */}
</Stack.Navigator>
);
}
Homepage
import {ClementineIcon, SectionHeader} from '#miniclementine:common/components';
import Colors from '#miniclementine:common/appearance/Colors';
import BlueButton from '#miniclementine:common/components/BlueButton';
import DiscoverMore from '#miniclementine:common/components/DiscoverMore';
export default function SessionHomepage({navigation, data, onPress}) {
console.log("data in HomePage", data)
const onPressSectionHeader = ({onPress}) => {
navigation.navigate('SESSIONS_LIST_PAGE', data)
};
const onPressSectionHeaderInvalid = () => {
alert('Out of scope for this task')
};
const Item = ({ item }) => (
<View style={styles.item}>
<TouchableOpacity style={styles.viewButton} onPress={() => {openSettingsModal(item) }}>
<Image source={item.image} style={styles.exerciseImage} />
<View style={styles.detailSection}>
<Text style={styles.title}>{item.title}</Text>
</View>
<ClementineIcon name="button-play" color={Colors.lilac} size={24} />
</TouchableOpacity>
</View>
);
const onContactPress = () => {
Linking.openURL('mailto:alina#clementineapp.co.uk?subject=SendMail&body=Description')
// Note: Not supported in iOS simulator, so you must test on a device.
// If you want to open an email client instead, I would suggest using the library react-native-email-link
}
return (
<SafeAreaView style={styles.container}>
<ScrollView>
<View style={styles.content}>
<SectionHeader
title="Morning Sessions"
onPress={onPressSectionHeaderInvalid}
textColor={Colors.Ink}
textColorSeeAll={Colors.cornflower}
/>
{/* <FlatList
data={DATA}
renderItem={({ item }) => <Item item={item} />}
keyExtractor={(item) => item.id}
/> */}
<DiscoverMore
title="Discover more sessions"
onPress={onPressSectionHeaderInvalid}
color={Colors.cornflower}
textColor={Colors.cornflower}
/>
<SectionHeader
title="Pick-me-ups"
onPress={onPressSectionHeader}
textColor={Colors.Ink}
textColorSeeAll={Colors.cornflower}
/>
<DiscoverMore
title="Discover more sessions"
onPress={onPressSectionHeader}
color={Colors.cornflower}
textColor={Colors.cornflower}
/>
</View>
<View style={styles.sleepSection}>
<Image
source={require('../../assets/illustrations/sleep_section.png')}
style={{height: 250, width: '100%'}}
/>
</View>
<View style={styles.sleepSection}>
<View style={styles.content}>
<View style={{paddingVertical: 10}}>
<SectionHeader
title="Sleep Sessions"
onPress={onPressSectionHeaderInvalid}
backgroundColor={Colors.ink}
textColor={Colors.stone}
textColorSeeAll={Colors.mint}
style={{paddingHorizontal: 10}}
/>
</View>
<Text>test</Text>
<DiscoverMore
title="Discover more sessions"
onPress={onPressSectionHeaderInvalid}
color={Colors.mint}
textColor={Colors.mint}
/>
</View>
</View>
<View style={{marginTop: '20%'}}></View>
<BlueButton title="Leave us feedback" onPress={onContactPress}/>
</ScrollView>
</SafeAreaView>
);
}
I am planning to put this data into a Flatlist inside the home page.
The best way to pass pros in navigation is to use params.
And as your stack is loaded with data you can use the initialParams like below
<Tab.Screen name="Sessions" component={SessionsStack} initialParams={{data:data}}/>
You can access it in SessionsStack like below
export default function SessionsStack({route}) {
.....
<Stack.Screen name={'SESSIONS_HOMEPAGE'} component={SessionsHomepage} initialParams={{data:route.params.data}} />
You can do this in the screens which are nested as well.
Warning: this patterns is good only if the data is loaded only once, if you are thinking of changing the data use something like react context.
Related
help, so lets say i got a bunch of data from an API (in Homescreen.js), which then i send to a component called "Artikel.js", how should i send the data in each of these articles to a screen called "DetailScreen.js". please someone help me, i'd appreciate it very very much, thanks in advance and sorry for bad english
const Homescreen = () => {
const [articles, setArticles] = useState([]);
const getArticles = () => {
axios
.get(
"https://newsapi.org/v2/top-headlines?country=us&apiKey=API_KEY",
{
params: {
category: "technology",
},
}
)
.then((response) => {
setArticles(response.data.articles);
})
.catch(function (error) {
console.log(error);
})
.then(function () {});
};
useEffect(() => {
getArticles();
}, []);
return (
<SafeAreaView style={styles.container}>
<FlatList
data={articles}
renderItem={({ item }) => (
<Artikel
urlToImage={item.urlToImage}
title={item.title}
description={item.description}
author={item.author}
publishedAt={item.publishedAt}
sourceName={item.source.name}
url={item.url}
/>
)}
keyExtractor={(item) => item.title}
/>
</SafeAreaView>
);
};
export default Homescreen;
Artikel.js
const Artikel = (props) => {
const navigation = useNavigation();
const goToDetail = () => {
navigation.navigate("Detail", {judul: 'Asu'});
};
// const goToSource = () => {
// WebBrowser.openBrowserAsync(props.url);
// };
return (
<SafeAreaView style={styles.container}>
<Pressable onPress={goToDetail}>
<Image
style={styles.image}
on
source={{
uri: props.urlToImage,
}}
/>
</Pressable>
<View style={{ paddingHorizontal: 20, paddingBottom: 10 }}>
<Text style={styles.title}>{props.title}</Text>
<Text style={styles.deskripsi} numberOfLines={3}>
{props.description}
</Text>
<View style={styles.data}>
<Text style={styles.h2}>
source:<Text style={styles.sumber}> {props.sourceName}</Text>
</Text>
<Text style={styles.tanggal}>
{moment(props.publishedAt).format("MMM Do YY")}
</Text>
</View>
</View>
</SafeAreaView>
);
};
export default Artikel;
"DetailScreen.js"
const DetailScreen = (props) => {
return (
<SafeAreaView style={styles.container}>
<Header />
<View style={styles.image}>
<Image
source={{
uri: props.thumbnail,
}}
style={styles.image}
/>
</View>
<View style={styles.bodyartikel}>
<Text style={styles.judul}>PROPS TITLE</Text>
<Text style={styles.artikel}>
PROPS.ARTICLE
</Text>
<View style={styles.footer}>
<Text style={styles.h1}>
By: <Text style={styles.sumber}>Salman</Text>
</Text>
<Text>12 Okt 2020</Text>
</View>
</View>
</SafeAreaView>
);
};
export default DetailScreen;
i tried to make a list of the datas i need in Artikel.js and made it into a list, but it didnt work
So in your Article.js you have called an method to navigate to DetailScreen.js. You have can do like this.
In Article.js:
<Pressable onPress={() => goToDetail(props)}> // pass props as argument
<Image
style={styles.image}
source={{
uri: props.urlToImage,
}}
/>
</Pressable>
now in your goToDetail method:
// Catch passed arguments as props
const goToDetail = (props) => {
navigation.navigate('Details', {
title: props.title,
description: props.description,
})
// As for now just passing title and description from props
};
Now to access Passed data in Detail.js:
import { useRoute } from '#react-navigation/native';
const DetailScreen = () => {
let route = useRoute(); // using route hooks
let {title, data} = route.params
return (
<YourComponent/>
);
};
In this way you can pass data from one screen to another. For more detail you always can visit react native navigation docs: https://reactnavigation.org/docs/params
I've been working on a React-Native project.
For export default function App() INSERT 1 to 3 (on code) works.
For export default class App extends Component none of the INSERT's works.
I have to combine them since the modal gives the user the ability to insert text inside the modal and then process the data to console.log and from there use the data.
export default class App extends Component {
{/* INSERT 1 before render also gives error */}
render () {
{/* INSERT 1 */}
const [list, setList] = useState();
const HandleAddList = () => {
console.log(list);
{/* INSERT 1 END */}
return (
<View>
<Modal
animationType = {"slide"}
transparent={false}
visible={this.state.isVisible}>
<View style={styles.ModalContext}>
<View style={styles.ModalNavigation}>
<Text style={[styles.closeText, styles.navText]}
onPress={() => {
this.displayModal(!this.state.isVisible);
}
}> Cancel </Text>
<Text style = {[styles.navHeader, styles.navText] }>
New</Text>
<Text style={[styles.doneText, styles.navText]}
onPress={() => {
this.displayModal(!this.state.isVisible);
{/* INSERT 2 */}
HandleAddList();
{/* INSERT 2 */}
}
}> Done </Text>
</View>
<TextInput
style={styles.inputText}
placeholder='Enter Something...'
{/* INSERT 3 */}
value = {list}
onChangeText={text => setList(text)}
{/* INSERT 3 */}
autoFocus
/>
</View>
</Modal>
{/* Rest of the code */}
</View>
{/* const stylesheets etc. */}
React-native's documentation told me that I can't use const inside a class component. (https://reactjs.org/warnings/invalid-hook-call-warning.html).
INSERT-comments were only for the purpose of the question and testing was done without it...
All the needed modules was imported from 'react-native'
Any solutions? Would be grateful if someone can help...
You can't use Hooks on Class Components, it's only a Functional Components' feature. Instead of that you could use this,I'm not pretty sure about some things but you can fix the errors:
import styles from './styles.css'
export default function App() {
const [list, setList] = useState();
const [isVisible, setIsVisible] = useState(true);
const HandleAddList = () => {
console.log(list);
}
return (
<View>
<Modal
animationType={"slide"}
transparent={false}
visible={isVisible}>
<View style={styles.ModalContext}>
<View style={styles.ModalNavigation}>
<Text style={[styles.closeText, styles.navText]}
onPress={() => {
setIsVisible(!isVisible);
}
}> Cancel </Text>
<Text style={[styles.navHeader, styles.navText]}>
New</Text>
<Text style={[styles.doneText, styles.navText]}
onPress={() => {
setIsVisible(!isVisible);
HandleAddList();
}
}> Done </Text>
</View>
<TextInput
style={styles.inputText}
placeholder='Enter Something...'
value={list}
onChangeText={text => setList(text)}
autoFocus
/>
</View>
</Modal>
</View>
)
}
I'm not used to Class Components, but I think this can guide you:
export default class App extends Component {
constructor() {
super()
this.state = {
isVisible: true,
list: ""
}
}
HandleAddList () {
console.log(this.state.list);
}
render () {
return (
<View>
<Modal
animationType={"slide"}
transparent={false}
visible={this.state.isVisible}>
<View style={styles.ModalContext}>
<View style={styles.ModalNavigation}>
<Text style={[styles.closeText, styles.navText]}
onPress={() => {
this.setState({...this.state, isVisible: !this.state.isVisible});
}
}> Cancel </Text>
<Text style={[styles.navHeader, styles.navText]}>
New</Text>
<Text style={[styles.doneText, styles.navText]}
onPress={() => {
this.setState({...this.state, isVisible: !this.state.isVisible});
this.HandleAddList();
}
}> Done </Text>
</View>
<TextInput
style={styles.inputText}
placeholder='Enter Something...'
value={this.state.list}
onChangeText={text => this.setState({ ...this.state, list: text})}
autoFocus
/>
</View>
</Modal>
</View>
)
}
}
It's so important you read the documentation (https://es.reactjs.org/docs/state-and-lifecycle.html) by yourself, there's a pair of things here you could fix reading it. It's a pleasure to help anyway, hope this works for you.
I updated my code thanks to your help.
When I launch the app with Expo, the opening works but I lost my scan icon which does not appear in my screen.
This icon appeared previously.
The idea is to scan some barcodes in order to display relevant data stemming from products.
Here is my new code:
import React, { useState, useEffect } from "react";
import {
StyleSheet,
Text,
View,
FlatList,
Button,
AsyncStorage,
} from "react-native";
import { useNavigation } from "#react-navigation/core";
import { TouchableOpacity } from "react-native-gesture-handler";
import { FontAwesome5 } from "#expo/vector-icons";
import { MaterialCommunityIcons } from "#expo/vector-icons";
import { ActivityIndicator } from "react-native-paper";
function ProductsScreen() {
const navigation = useNavigation();
const [data, setData] = useState([]);
const [isLoading, setisLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
const data = await AsyncStorage.getItem("userData");
setData(data);
setisLoading(false);
};
fetchData();
}, []);
console.log(data);
return isLoading ? (
<ActivityIndicator />
) : (
<>
{data ? (
<FlatList
data={dataArray}
keyExtractor={(item) => item.name}
renderItem={({ item }) => (
<>
<Text>{item.brand}</Text>
<View style={styles.scan}>
<MaterialCommunityIcons
name="barcode-scan"
size={40}
color="black"
onPress={() => {
navigation.navigate("CameraScreen");
}}
/>
</View>
</>
)}
/>
) : null}
</>
);
}
export default ProductsScreen;
I would appreciate your comments please.
You could use ? (optional chaining) to confirm data doesnt yield to undefined before mapping.
data?.map((data, index) => {return <>....</>}
You need to return from data.map function to render the array items
return isLoading ? (
<ActivityIndicator />
) : (
<>
{data?.map((data, index) => {
return <View key ={index}>
<Text> {data.products_name_fr} </Text>
<Text> {data.brands} </Text>
<Text> {data.image_url} </Text>
<View style={styles.scan}>
<MaterialCommunityIcons
name="barcode-scan"
size={40}
color="black"
onPress={() => {
navigation.navigate("CameraScreen");
}}
/>
</View>
</View>;
})}
</>
);
Or short-hand of return
return isLoading ? (
<ActivityIndicator />
) : (
<>
data?.map((data, index) => (
<View key ={index}>
<Text> {data.products_name_fr} </Text>
<Text> {data.brands} </Text>
<Text> {data.image_url} </Text>
<View style={styles.scan}>
<MaterialCommunityIcons
name="barcode-scan"
size={40}
color="black"
onPress={() => {
navigation.navigate("CameraScreen");
}}
/>
</View>
</View>;
))
</>
);
I changed my code like this but I have the same error. Besides, the part of code which begins from: const styles=Stylesheet.create seems to be not active
import React, { useState, useEffect } from "react";
import { StyleSheet, Text, View, Button, AsyncStorage } from "react-native";
import { useNavigation } from "#react-navigation/core";
import { TouchableOpacity } from "react-native-gesture-handler";
import { FontAwesome5 } from "#expo/vector-icons";
import { MaterialCommunityIcons } from "#expo/vector-icons";
import { ActivityIndicator } from "react-native-paper";
import axios from "axios";
function ProductsScreen() {
const navigation = useNavigation();
const [data, setData] = useState([]);
const [isLoading, setisLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
const data = await AsyncStorage.getItem("userData");
setisLoading(false);
setData(data);
};
fetchData();
}, []);
return isLoading ? (
<ActivityIndicator />
) : (
<>
{data?.map((data, index) => {
return (
<>
key ={index}
<Text> {data.products_name_fr} </Text>
<Text> {data.brands} </Text>
<Text> {data.image_url} </Text>
<View style={styles.scan}>
<MaterialCommunityIcons
name="barcode-scan"
size={40}
color="black"
onPress={() => {
navigation.navigate("CameraScreen");
}}
/>
</View>
</>
);
})}
</>
);
const styles = StyleSheet.create({
products: {
alignItems: "center",
justifyContent: "center",
},
scan: {
marginLeft: 30,
position: "absolute",
bottom: 0,
right: 20,
marginBottom: 60,
marginRight: 30,
padding: 10,
borderRadius: 10,
backgroundColor: "#ff9234",
},
});
}
export default ProductsScreen;
I changed a little bit my code and I got another type of error : Invariant violation: Text strings must be rendered within a component. I will really appreciate your comments and support to fix this
return isLoading ? (
<ActivityIndicator />
) : (
<>
data?.map((data, index) => (
<>
<Text> {data.products_name_fr} </Text>
<Text> {data.brands} </Text>
<Text> {data.image_url} </Text>
<View style={styles.scan}>
<MaterialCommunityIcons
name="barcode-scan"
size={40}
color="black"
onPress={() => {
navigation.navigate("CameraScreen");
}}
/>
</View>
</>
))
</>
);
}
In the useEffect, set the data as array. Example
const = [data, setData] = useState([]); // do this in your state
setData([data]); //do this in your useEffet hook
I am using React-Native-Paper Menu on the header to show two items: Logout and Profile
However, I can't seem to navigate to different screen when pressing
Logout item.
I have included snack workable example, code snippet, and screenshot below:
Snack Example
Code Snippet:
App.js
import { TextInput, Button, Menu, Divider, Provider } from 'react-native-paper';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import AntDesign from 'react-native-vector-icons/AntDesign';
import Register from './Register';
import Logout from './Logout';
const Stack = createStackNavigator();
const CustomMenu = () => {
const [showMenu, setShowMenu] = React.useState(false);
return (
<View style={{}}>
<Menu
visible={showMenu}
onDismiss={() => setShowMenu(false)}
anchor={
<TouchableOpacity onPress={() => setShowMenu(true)}>
<MaterialCommunityIcons
name="earth"
size={30}
style={{ color: 'black' }}
/>
</TouchableOpacity>
}>
<Menu.Item
title="Logout"
onPress={() => {
setShowMenu(false)
/* THE FOLLOWING DOESN'T WORK */
//navigation.navigate('Logout')
}}
/>
<Divider />
<Menu.Item
onPress={() => {
setShowMenu(false)
}}
title="Profile"
/>
</Menu>
</View>
);
};
function App() {
return (
<Provider>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Register"
component={Register}
options={({ navigation, route }) => ({
headerTitle: () => (
<View style={{ flexDirection: 'row' }}>
{
/*THIS WORKS*/
<TouchableOpacity
onPress={() => navigation.navigate('Logout')}
>
<MaterialCommunityIcons name="settings" size={30} style={{
color: 'black' }} />
</TouchableOpacity>
/*THIS WORKS*/
}
<View><CustomMenu /></View>
<TouchableOpacity
onPress={() => navigation.navigate('MenuV2')}
>
<Text>
Menu
</Text>
</TouchableOpacity>
</View>
),
headerStyle: {
backgroundColor: '#2e46ff',
},
})}
/>
<Stack.Screen name="Logout" component={Logout}/>
</Stack.Navigator>
</NavigationContainer>
</Provider>
);
}
export default App;
Screenshot:
You can use the useNavigation hook inside the custom component
As its inside navigation scope it will work as expected
const CustomMenu = () => {
const [showMenu, setShowMenu] = React.useState(false);
const navigation = useNavigation();
return (
<View style={{}}>
<Menu
visible={showMenu}
onDismiss={() => setShowMenu(false)}
anchor={
<TouchableOpacity onPress={() => setShowMenu(true)}>
<MaterialCommunityIcons
name="earth"
size={30}
style={{ color: 'black' }}
/>
</TouchableOpacity>
}>
<Menu.Item
title="Logout"
onPress={() => {
setShowMenu(false);
}}
/>
<Divider />
<Menu.Item
onPress={() => {
setShowMenu(false);
navigation.navigate('Logout');
}}
title="Profile"
/>
</Menu>
</View>
);
};
Also consider using Authentication flow for login logout scenarios.
You need to pass navigation (or use the useNavigation hook) to be able to navigate from your menu:
<View><CustomMenu navigation={navigation} /></View>
...
const CustomMenu = ({ navigation }) => {
const [showMenu, setShowMenu] = React.useState(false);
return (
<View style={{}}>
<Menu
visible={showMenu}
onDismiss={() => setShowMenu(false)}
anchor={
<TouchableOpacity onPress={() => setShowMenu(true)}>
<MaterialCommunityIcons
name="earth"
size={30}
style={{ color: 'black' }}
/>
</TouchableOpacity>
}>
<Menu.Item
title="Logout"
onPress={() => {
setShowMenu(false)
navigation.navigate('Logout');
}}
/>
<Divider />
<Menu.Item
onPress={() => {
setShowMenu(false)
}}
title="Profile"
/>
</Menu>
</View>
);
};
I am fetching data from my server but is loading without indicator how I can add an indicator to my code? I want show loading indicator before fetching from server. Unfortunately, I'm not sure how to create a loader to wait for the data to load. Here is my currently code.
Here is my code
import { SectionList, Alert, ActivityIndicator } from 'react-native'
import Icon from 'react-native-vector-icons/Ionicons';
import styled from 'styled-components/native';
import Swipeable from 'react-native-swipeable-row';
import axios from "axios";
import { Appointment, SectionTitle } from '../components';
const HomeScreen = ({ navigation }) => {
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const fetchAppointments = () => {
setIsLoading(true);
axios.get('https:*********')
.then(({ data }) => {
setData(data.data);
setIsLoading(false);
});
}
useEffect(fetchAppointments, []);
useEffect(fetchAppointments, [navigation.state.params]);
return (
<Container>
{data && ( <SectionList
sections={data}
keyExtractor={item => item._id}
onRefresh={fetchAppointments}
refreshing={isLoading}
renderItem={({ item }) => (
<Swipeable
rightButtons={[
<SwipeViewButton style={{ backgroundColor: '#B4C1CB' }}>
<Icon name="md-create" size={28} color="white" />
</SwipeViewButton>,
<SwipeViewButton
onPress={removeAppointment.bind(this, item._id)}
style={{ backgroundColor: '#F85A5A' }}
>
<Icon name="ios-close" size={48} color="white" />
</SwipeViewButton>
]}
>
<Appointment navigate={navigation.navigate} item={item} />
</Swipeable>
)}
renderSectionHeader={({ section: { title } }) => (
<SectionTitle>{title}</SectionTitle>
)}
/>)}
</Container>
)};
You could do this
import { SectionList, Alert, ActivityIndicator } from 'react-native'
import Icon from 'react-native-vector-icons/Ionicons';
import styled from 'styled-components/native';
import Swipeable from 'react-native-swipeable-row';
import axios from "axios";
import ActivityIndicator from 'react-native';
import { Appointment, SectionTitle } from '../components';
const HomeScreen = ({ navigation }) => {
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const fetchAppointments = () => {
setIsLoading(true);
axios.get('https:*********')
.then(({ data }) => {
setData(data.data);
setIsLoading(false);
});
}
useEEffect(fetchAppointments, []);
useEffect(fetchAppointments, [navigation.state.params]);
return (
<Container>
{isLoading ? (
<ActivityIndicator size="large" color="#0000ff" />
) : (
<>
{data && ( <SectionList
sections={data}
keyExtractor={item => item._id}
onRefresh={fetchAppointments}
refreshing={isLoading}
renderItem={({ item }) => (
<Swipeable
rightButtons={[
<SwipeViewButton style={{ backgroundColor: '#B4C1CB' }}>
<Icon name="md-create" size={28} color="white" />
</SwipeViewButton>,
<SwipeViewButton
onPress={removeAppointment.bind(this, item._id)}
style={{ backgroundColor: '#F85A5A' }}
>
<Icon name="ios-close" size={48} color="white" />
</SwipeViewButton>
]}
>
<Appointment navigate={navigation.navigate} item={item} />
</Swipeable>
)}
renderSectionHeader={({ section: { title } }) => (
<SectionTitle>{title}</SectionTitle>
)}
/>)}
</>
)}
</Container>
)};
Create a functional component that returns some styled activity indicator. Something like this:
<View style={{styles.yourIndicatorStyle}}> //give the position and opacity or whatev you want
<ActivityIndicator
size={"large"}
color={"green"}
animating={true} />
</View>
import it in your home screen an use it like:
<Container>
{isLoading && <YourIndicatorComponent />}
...
</Container>
React 16.6 added a component that lets you “wait” for some
code to load and declaratively specify a loading state (like a
spinner) while we’re waiting:
const ProfilePage = React.lazy(() => import('./ProfilePage')); // Lazy-loaded
// Show a spinner while the profile is loading
<Suspense fallback={<Spinner />}>
<ProfilePage />
</Suspense>
Documentation