react-native how do I show activityindicator while file uploading - javascript

I want to have a loading spinner appear in the middle of the screen while the file is being uploaded.
The clicked file is loaded and appears in the file list as well.
I imported ActivityIndicator from 'react-native'.
When I wrote the code after as a test, the loading spinner was well seen.
However, I wanted to make the spinner appear only the file is loaded. So, I wrote the code, but the loading spinner does not appear.
import {Text,View,ImageBackground,Image,StyleSheet,TouchableOpacity,FlatList,Button,ActivityIndicator} from 'react-native';
export default function FileUpload({route, navigation}) {
const [multipleFile, setMF] = useState([])
const [isLoading, setLoading] = useState(true);
useEffect(() => {
setTimeout(() => {
setLoading(false);
}, 5000);
}, [])
const addEntry = (data) => {
let newObj = {
"id": randId(),
"name" : data.filename,
"text" : data.text,
}
console.log('Finish load');
setMF([...multipleFile, newObj]);
console.log(multipleFile)
};
const randId = () => {
let id = ''
for (var i = 0; i < 10; i++) {
id += String.fromCharCode(Math.trunc(Math.random()*85) + 48)
}
return id
}
const sendFile = () => {
axios({
method: 'post',
url: '',
data: {
"uri": ""
}
}).then((res) =>{
addEntry(res.data)
}
).catch((err) => console.log(err));
}
const renderItem = ({ item }) => (
<Text>{item.name}</Text>
);
return (
<ImageBackground source={require('../images/bg2.png')}
style={{width: '100%', height: '100%'}}>
<View>
<TouchableOpacity onPress={() => {
DocumentPicker.getDocumentAsync().then((res) => {
console.log(res)
if (res.type == 'success') {
console.log('load start');
if(isLoading){
return(
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<ActivityIndicator size="large"/>
</View>
);
}
sendFile()
} else {
console.log('you cancelled')
}
})
}}
style={{alignItems: 'center'}}>
<Image source ={require('../images/cloud.png')}
style={styles.image}
/>
<View style={styles.viewTextStyle}>
<Text style={styles.textStyle}>{'Upload Files'} </Text>
<Text style={{fontSize:60, color:'white'}}> + </Text>
<Text style={styles.textStyle1}>{'Browse and select your file \n you want to upload'}</Text>
</View>
</TouchableOpacity>
</View>
<View style={styles.listHeader}>
<Text style={{textAlign: 'center', fontSize: 18}}> File List </Text>
</View>
<FlatList
style={styles.scrollContainer}
data={multipleFile}
renderItem={renderItem}
keyExtractor={item => item.id.toString()}>
</FlatList>
{/* <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<ActivityIndicator size="large"/>
</View> */}
<TouchableOpacity onPress={() => {
// console.log(multipleFile[0].name)
navigation.navigate('Details Search',
multipleFile[0]
)}}>
<View style={styles.button}>
<Text style={styles.buttonText}>Next</Text>
</View>
</TouchableOpacity>
</ImageBackground>
);
}

set the default state to false
const [isLoading, setLoading] = useState(false);
remove this effect
useEffect(() => {
setTimeout(() => {
setLoading(false);
}, 5000);
}, [])
remove loading view from DocumentPicker.getDocumentAsync()
if (res.type == 'success') {
sendFile()
} else {
console.log('you cancelled')
}
set loading true/false in sendFile()
const sendFile = () => {
setLoading(true);
axios({
method: 'post',
url: '',
data: {
"uri": ""
}
}).then((res) =>{
setLoading(false)
addEntry(res.data)
}
).catch((err) => setLoading(false));
}
const renderItem = ({ item }) => (
<Text>{item.name}</Text>
);
add loading view in main return
return (
....
if(isLoading){
return(
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<ActivityIndicator size="large"/>
</View>
);
}
....
)

Related

React native onPress or any event is not working after sometime of app load

I am using react native thunder push where continually value fluctuation happening and i am showing data on screen using mobx state management tool. all things is working fine but when i am leave the screen for 2 minute then that events are not working screen is not freezing only events is not working.
STORE
import {observable,action,makeAutoObservable} from 'mobx';
class CommonMob {
data =[];
checkAppstate ='active';
deployeStatus = true;
queryString = '?creator_id=null&tags=&exchange=null&broker_id=null&instrument_type=null&execution=null&status=null&pnl=null&broker_id=';
userToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9hcGktYXBwLnRyYWRldHJvbi50ZWNoXC9hdXRoXC9zaWduLWluIiwiaWF0IjoxNjU0ODYzMjcyLCJleHAiOjIzNTQ3MDMyNzIsIm5iZiI6MTY1NDg2MzI3MiwianRpIjoicVF6TTJHUkdQS3kyY0NCeCIsInN1YiI6MjY3NTE5LCJwcnYiOiIyM2JkNWM4OTQ5ZjYwMGFkYjM5ZTcwMWM0MDA4NzJkYjdhNTk3NmY3In0.QLDx1SUEJBheQbm-UqD8AOad5Oj3x3UWHBeShmn-2PE';
constructor() {
makeAutoObservable(this)
}
setData(res) {
this.data =res;
}
setAppState(val){
this.checkAppstate = val;
}
setdeployeStatus(val){
this.deployeStatus = val;
}
}
export default new CommonMob()
Screen
import {TouchableOpacity,View, Text, Button, FlatList, AppState,ScrollView,InteractionManager} from 'react-native';
import React, {useCallback, useEffect} from 'react';
import deployedStore from '../mob/deployedStore';
import {useIsFocused, useFocusEffect} from '#react-navigation/native';
import MarketStore from '../mob/deployedStore';
import {observer} from 'mobx-react-lite';
import {initThunderPush} from '../Service/ThunderConnection';
import {
fetchStrategies,
fetchFullStrategies,
} from '../Service/DeployeConnection';
import CommonStore from '../mob/commonStore';
import commonStore from '../mob/commonStore';
import Nav from '../Nav/Nav';
import { useNavigation } from '#react-navigation/native';
// import commonStore from '../mob/commonStore';
let listening = false;
const Deplyee = React.memo(observer(({navigation}) => {
// const navigation = useNavigation();
const navFun = ()=>{
alert("function call");
navigation.navigate("Dashboard")
}
useFocusEffect(
useCallback(() => {
// Do something when the screen is focused.
deployedStore.setisDeploye(true);
deployedStore.setisMarcketWatch(true);
commonStore.setdeployeStatus(true);
return () => {
// Do something when the screen is unfocused
deployedStore.setisDeploye(false);
deployedStore.setisMarcketWatch(false);
commonStore.setdeployeStatus(false);
};
}, []),
);
// React.useEffect(() => {
// }, [deployedStore.dataaa, deployedStore.strategies]);
React.useEffect(
() => {
InteractionManager.runAfterInteractions(() => {
// let timer = setTimeout(() => , 1000)
fetchFullStrategies(CommonStore.userToken);
fetchStrategies();
// fetchFullStrategies(CommonStore.userToken);
initThunderPush();
return () => {
clearTimeout(timer)
}
});
},
[[deployedStore.dataaa, deployedStore.strategies]]
)
React.useEffect(() => {
fetchStrategies();
}, [deployedStore.strategies]);
useFocusEffect(
React.useCallback(() => {
// fetchFullStrategies(CommonStore.userToken);
}, [deployedStore.strategies]),
);
React.useEffect(
() => {
if (!listening) {
initThunderPush();
listening = true;
}
setInterval(() => {
deployedStore.setCanState(true);
}, 1000);
},
[
/*strategies*/
],
);
useEffect(() => {
const appStateListener = AppState.addEventListener(
'change',
nextAppState => {
commonStore.setAppState(nextAppState);
},
);
return () => {
appStateListener?.remove();
};
}, []);
return (
<View>
<ScrollView>
<View
style={{
display: 'flex',
flexDirection: 'row',
width: '100%',
margin: 'auto',
flexWrap: 'wrap',
}}>
<Nav />
<TouchableOpacity onPress={() => alert("test pass")} ><Text>Test alert</Text></TouchableOpacity>
<TouchableOpacity onPress={() => navFun()} >
<Text>test function </Text>
</TouchableOpacity>
</View>
<Text>Deployed Strategies</Text>
{deployedStore.strategies.map(item => (
<View key={item.identifier}>
<Text style={{color: 'red', alignSelf: 'center'}}>
NAME - {item.template.name}
</Text>
<Text style={{color: 'blue', alignSelf: 'center'}}>
TYPE - {item.deployment_type}
</Text>
<Text style={{color: 'green', alignSelf: 'center'}}>
STATUS {item.status}
</Text>
<Text style={{color: 'orange', alignSelf: 'center', fontSize: 20}}>
{/* <Text style={item.sum_of_pnl >= 0 ? {color:green} : {color:red}}> */}
{item.country === 'IN'
? `${(item.sum_of_pnl, 0)} (${(
(item.sum_of_pnl /
(item.template.capital_required * item.minimum_multiple)) *
100
).toFixed(2)} %)`
: null}
</Text>
{/* <Text style={{color:'green', alignSelf:'center'}}>{item.ltp}</Text> */}
</View>
))}
<Text>market watch section</Text>
{deployedStore.dataaa.map(item => (
<View key={item.identifier}>
<Text style={{color: 'red', alignSelf: 'center'}}>
{item.identifier}
</Text>
<Text style={{color: 'green', alignSelf: 'center'}}>{item.ltp}</Text>
</View>
))}
</ScrollView>
</View>
);
}));
export default React.memo(Deplyee);

How to display posted data without refresh screen in React Native?

I have a screen that takes care of creating a garden, I have another screen that is used to display the garden (therefore its name, its image, etc.).
So in my first screen which is used to create the garden I make a post request to create it as you can see below. And in my second screen I call my API by making a GET request to retrieve the data from the garden I just created.
But the problem is that I have to constantly reload the application to see the garden appear... How can I ensure that with each new creation the garden state is updated with the new data that has just appeared?
Here is the code of first screen (POST request) :
export default function FormCreateGarden({navigation}) {
const [loading, setLoading] = useState(false);
const [user, setUser] = useState({});
const [garden, setGarden] = useState(false);
const [gardenName, setGardenName] = useState('');
const [gardenImage, setGardenImage] = useState({uri: '', type: '', name: ''});
const [isVisible, setIsVisible] = useState(false);
const baseUrl = 'http://127.0.0.1/api';
const submitButton = async () => {
if (!gardenName.trim()) {
alert("Veuillez renter un nom de jardin s'il vous plait!");
return;
}
setLoading(true);
try {
const jsonValue = await AsyncStorage.getItem('user');
const parsedUserData = JSON.parse(jsonValue) || {};
setUser(parsedUserData);
const myHeaders = new Headers();
myHeaders.append('Authorization', `Token ${parsedUserData.token}`);
const photo = {
uri: gardenImage.uri,
type: gardenImage.type,
name: gardenImage.name,
};
const formdata = new FormData();
formdata.append('name', gardenName);
formdata.append('user', parsedUserData.user.id);
formdata.append('image', photo);
const requestOptions = {
method: 'POST',
headers: myHeaders,
body: formdata,
redirect: 'follow',
};
const response = await fetch(`${baseUrl}/garden/`, requestOptions);
if (response.status === 201) {
let data = await response.json();
alert(`Votre jardin "${gardenName}" a bien été crée`);
setLoading(false);
setGardenName('');
setGardenImage({uri: '', type: '', name: ''});
navigation.navigate('GardenHome');
} else {
throw new Error('Erreur');
}
} catch (e) {
setLoading(false);
console.log(e.message);
console.log(e);
}
};
return (
<View style={styles.container}>
<View>
<Text>
Créez votre jardin :
</Text>
<View>
<Text>Nom de votre jardin :</Text>
<TextInput
placeholder="Mon jardin"
placeholderTextColor={'gray'}
onChangeText={text => setGardenName(text)}
value={gardenName}
/>
</View>
<View>
<Text>Ajouter une photo</Text>
{gardenImage.uri === '' ? (
<TouchableWithoutFeedback onPress={() => setIsVisible(true)}>
<View>
<FontAwesomeIcon
icon={faCamera}
size={30}
/>
</View>
</TouchableWithoutFeedback>
) : (
<Image
source={{uri: gardenImage.uri}}
/>
)}
<BottomSheet modalProps={{}} isVisible={isVisible}>
{list.map((l, i) => (
<ListItem
key={i}
containerStyle={l.containerStyle}
onPress={l.onPress}>
<ListItem.Content>
<ListItem.Title style={l.titleStyle}>
{l.title}
</ListItem.Title>
</ListItem.Content>
</ListItem>
))}
</BottomSheet>
</View>
<View>
<View>
<Button
title="Annuler"
color={'black'}
onPress={cancelButton}
/>
</View>
<View>
<Button
title="Valider"
color={'white'}
onPress={submitButton}
/>
</View>
</View>
</View>
);
}
Here is the code of second screen (GET request) :
export default function GardenHome() {
const [garden, setGarden] = useState([]);
const [loading, setLoading] = useState(false);
const navigation = useNavigation();
const gardenData = async () => {
setLoading(true);
const user = await AsyncStorage.getItem('user');
const parsedUserData = JSON.parse(user);
try {
const response = await axios.get(
`http://127.0.0.1/api/garden?user=${parsedUserData.user.id}`,
{
headers: {
Authorization: `Token ${parsedUserData.token}`,
},
},
);
if (response.status === 200) {
setGarden(response.data);
setLoading(false);
}
} catch (e) {
console.log('Erreur ' + e);
setLoading(false);
}
};
useEffect(() => {
gardenData();
}, []);
const gardenJSX = garden.map(item => {
return (
<View style={{flex: 0.75}} key={item.id}>
<Image
source={{uri: item.image}}
style={{marginTop: 15, width: '100%', height: 150}}
/>
<View>
<View
style={{
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'center',
}}>
</View>
</View>
</View>
);
});
if (loading) {
return (
<View style={{flex: 1, justifyContent: 'center'}}>
<ActivityIndicator size="large" color="#3c693d" />
</View>
);
} else {
return (
<View style={styles.container}>
<Heading name="Jardin de" />
<View style={styles.content}>
<View style={{height: '65%'}}>
<ScrollView>{gardenJSX}</ScrollView>
</View>
<HerbGarden />
</View>
</View>
);
}
}
Thanks for help !

How to make reusable component in react-native and call them inside other component?

I have a modal component that I want to reuse in future component.
For this reason I want to have it in its own file.
I don't manage to call the component inside the other properly though.
Here is my last attempt of it.
The Modal component code:
export const FlyingDescription = (cityDescription) => {
const [modalVisible, setModalVisible] = useState(false);
return (
<View>
<Modal
animation="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => setModalVisible(!modalVisible)}
>
<View style={styleBoxParent}>
<View style={styleBoxChildren}>
<LinearGradient
style={styleLinearGradient}
colors={['#136a8a', '#267871']}
start={[0, 0.65]}
>
<Text style={styleText}>{cityDescription}</Text>
<Pressable
onPress={() => setModalVisible(!modalVisible)}
>
<Text style={styleText}>Close</Text>
</Pressable>
</LinearGradient>
</View>
</View>
</Modal>
</View>
);
};
The component where I want to call the Modal component:
import FlyingDescription from './FlyingDescription.js';
var utils = require('./utils');
export default class SearchScreen extends React.Component {
constructor(props) {
super(props);
this.navigation = props.navigation;
this.state = {
searchInput: '',
item : {},
renderSearch: false,
renderFlyingDescription: false,
};
this.errorMessage = 'Search for cities...';
}
resetState = () => {
this.setState({
item: {},
renderable: false,
}); }
setSearchInput = (value) => {
this.setState({
searchInput: value
});
}
searchCity = () => {
this.resetState();
utils.fetchWeather(this.state.searchInput).then(response => {
if (response.cod == 200) {
console.log(response);
this.setItemState(
{
name: response.name,
temp: Math.ceil(response.main.temp),
type: response.weather[0].main,
desc: 'Humidity: ' + response.main.humidity + '% - ' + response.weather[0].main
}
);
this.setRenderSearch();
}
});
}
setItemState = (newItem) => {
this.setState(
{
item: newItem,
}
);
}
setRenderSearch = () => {
this.setState(
{
renderSearch: true,
}
);
}
render = () => {
return(
<View style={utils.style.container}>
<StatusBar barStyle="light-content" />
<Text style={utils.style.titleContainer}>☀️ CityWeather</Text>
<View style={{alignItems: 'center', width:'90%'}}>
<Text>Search for a city</Text>
<TextInput
onChangeText={(value) => this.setSearchInput(value)}
value={this.searchInput}
style={{ width: '80%', padding: 15, margin: 5, backgroundColor: 'black', color: 'white' }}
/>
<TouchableHighlight
style={{backgroundColor: 'grey', padding: 20, borderRadius: 8}}
onPress={this.searchCity}
>
<Text style={{fontSize: 14, color:'white'}}>Search</Text>
</TouchableHighlight>
</View>
{ this.state.renderSearch ? (
<TouchableHighlight
underlayColor="white"
onPress={ () => this.setState({renderFlyingDescription: true})}
>
<LinearGradient
colors={['rgba(0,0,0,0.05)', 'rgba(0,0,0,0)']}
start={[0, 0.5]}
>
<View style={utils.style.row}>
<Text style={[utils.getTempRange(this.state.item.temp), utils.style.temp]}>
{utils.getEmoji(this.state.item.type)} {this.state.item.temp} °C
</Text>
<Text style={utils.style.cityName}>{this.state.item.name}</Text>
</View>
</LinearGradient>
</TouchableHighlight>
) : (
// WHERE I WANT TO RENDER MY MODAL COMPONENT
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center', fontSize: 32}}>
<Text>{this.errorMessage}</Text>
</View>
)
}
{
renderFlyingDescription(this.state.renderFlyingDescription, this.state.item.desc)
}
</View>
);
}
}
export function renderFlyingDescription(isInterpretable, cityDescription) {
if(isInterpretable) {
return <FlyingDescription cityDescription={cityDescription} />
}
}

too many rerenders on using useState

I am calling the contactsfunction from the main return. I don't see any error until here:
const showContacts = React.useCallback(
(data: UsersQueryHookResult) => {
if (data) {
return (
<View style={styles.users}>
</View>
);
}
},
[userData],
);
const contacts = () => {
console.log('running');
const { loading, error, data } = useUsersQuery({
variables: {
where: { id: 34 },
},
});
console.log('DATA COMING', data);
//setUserData(data);
//console.log('contact name', data.users.nodes[0].userRelations[0].relatedUser.firstName);
};
return (
<SafeAreaView style={{ flex: 1 }}>
<Container style={{ flex: 1, alignItems: 'center' }}>
<Item style={styles.addToWhitelist}>
<Icon
name="add"
onPress={() => navigation.navigate('AddContactTry')}
/>
<Text style={styles.addToContactTitle}>Add contact</Text>
</Item>
<Text onPress={() => navigation.navigate('Home')}>Zurück</Text>
<View style={{ width: moderateScale(350) }}>
<Text>Keine Kontacte</Text>
</View>
{contacts()}
</Container>
</SafeAreaView>
);
};
Now I want to do some conditional rendering on the basis of the results from contacts. However, as soon as I uncomment setUserData(data); I get an error that too many re-renders. I don't get what I am doing wrong in showUsersto get this error.
Edit:
I tried this but it gives an invalid hook call error:
export const Whitelist: React.FunctionComponent = (props) => {
const [userData, setUserData] = useState<UsersQueryHookResult>('');
useEffect(() => {
// Your function to fetch/get contacts
const data = contacts();
setUserData(data);
}, [])
const showContacts = React.useCallback(
(data: UsersQueryHookResult) => {
if (data) {
return (
<View style={styles.users}>
</View>
);
}
},
[userData],
);
const contacts = () => {
console.log('running');
const { loading, error, data } = useUsersQuery({
variables: {
where: { id: 34 },
},
});
console.log('DATA COMING', data);
//setUserData(data);
};
return (
<SafeAreaView style={{ flex: 1 }}>
<Container style={{ flex: 1, alignItems: 'center' }}>
<Item style={styles.addToWhitelist}>
<Icon
name="add"
onPress={() => navigation.navigate('AddContactTry')}
/>
<Text style={styles.addToContactTitle}>Add contact</Text>
</Item>
<Text onPress={() => navigation.navigate('Home')}>Zurück</Text>
{/* {contacts()} */}
</Container>
</SafeAreaView>
);
};
Try to fetch contacts in componentDidMount method or useEffect (in your case with hooks) and store the result in a state with useState.
const [contacts, setContacts] = React.useState(null);
[...]
React.useEffect(() => {
// Your function to fetch/get contacts
const data = contacts();
setContacts(data);
}, [])
[...]
return (
<SafeAreaView style={{ flex: 1 }}>
[...]
{contacts && contacts.map(contact => (<View>{contact.name}</View>)}
[...]
</SafeAreaView>
);
hope it helps.

React Native & Firebase Search

I am trying to use firebase and perform a search. The trouble I am having is when I type the search text the list data isn't being updated.
Below is the code I have come up with
componentDidMount() {
this.setState({loading: true});
var merchants = new Array;
merchantsRef.once('value').then((snapshot) => {
snapshot.forEach((child) => {
merchants.push({
id: child.val().id,
type: child.val().type,
attributes: {
coming_soon: child.val().attributes.coming_soon,
featured_image_url: child.val().attributes.featured_image_url,
has_locations: child.val().attributes.has_locations,
highlight: child.val().attributes.highlight,
logo_url: child.val().attributes.logo_url,
main_image_url: child.val().attributes.main_image_url,
name: child.val().attributes.name,
offer_active: child.val().attributes.offer_active,
offer_cta_title: child.val().attributes.offer_cta_title,
offer_ends_at: child.val().attributes.offer_ends_at,
offer_starts_at: child.val().attributes.offer_starts_at,
offer_teaser: child.val().attributes.offer_teaser,
offer_terms: child.val().attributes.offer_terms,
offer_text: child.val().attributes.offer_text,
offer_url: child.val().attributes.offer_url,
permalink: child.val().attributes.permalink,
shop_url: child.val().attributes.shop_url,
},
_key: child.key
})
})
this.setState({
data: merchants,
loading: false,
})
// console.log(this.state.data)
}).catch((error) => {
console.log('Error fetching retailer data:', error)
})
}
searchFilterFunction = text => {
merchantsRef.orderByChild('name').startAt(text.toString()).on('value', function(child) {
console.log(child.val());
});
};
_renderEmpty = () => {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<ActivityIndicator />
</View>
)
}
_renderItem = ({item}) => (
<MerchantRow data={item} />
)
_keyExtractor = (item, index) => item._key;
render() {
if (this.state.loading) {
console.log("Loading")
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<ActivityIndicator
animating
size="large"
/>
<Text>Fetching shops...</Text>
</View>
)
}
return (
<View style={styles.container}>
<SearchBar
placeholder='Search for retailers...'
containerStyle={{backgroundColor: Colors.blue, borderTopWidth: 0, borderBottomWidth: 0}}
inputStyle={{backgroundColor: Colors.snow}}
onChangeText={text => this.searchFilterFunction(text)}
autoCorrect={false}
/>
<ScrollView style={styles.container}>
<FlatList
data={this.state.data}
renderItem={this._renderItem.bind(this)}
keyExtractor={this._keyExtractor}
initialNumToRender={9}
ItemSeparatorComponent={this._renderSeparator}
removeClippedSubviews={false}
ListEmptyComponent={this._renderEmpty}
/>
</ScrollView>
</View>
)
}
#Paul'Whippet'McGuane, good to know. That's likely because the context of this isn't defined. In order to maintain the context of the keyword this, you can modify the searchFilterFunction like so:
searchFilterFunction = text => {
const that = this;
merchantsRef.orderByChild('name').startAt(text.toString()).on('value', function(child) {
console.log(child.val());
const val = child.val();
that.setState({ data: val });
});
};

Categories