How to set a state to refresh a google-map-content automatically - javascript

I built a small boat visualizer. I am using AISHub APIs. After fetching data from the APIs I am able to obtain a json file with the vessels I am interested in and inject these vessels inside a table.
The user has to manually update the page pushing the refresh button on top left of the page to see the new updated table.
The problem: How to set a state to refresh the google-map content automatically every minute instead of the user doing it manually?
Below the code:
GoogleMap.js
class BoatMap extends Component {
constructor(props) {
super(props);
this.state = {
buttonEnabled: true,
buttonClickedAt: null,
progress: 0,
ships: [],
type: 'All',
shipTypes: [],
activeShipTypes: [],
logoMap: {}
};
this.updateRequest = this.updateRequest.bind(this);
this.countDownInterval = null;
}
async componentDidMount() {
this.countDownInterval = setInterval(() => {
if (!this.state.buttonClickedAt) return;
const date = new Date();
const diff = Math.floor((date.getTime() - this.state.buttonClickedAt.getTime()) / 1000);
if (diff < 90) {
this.setState({
progress: diff,
buttonEnabled: false
});
} else {
this.setState({
progress: 0,
buttonClickedAt: null,
buttonEnabled: true
});
}
}, 500);
await this.updateRequest();
const shipTypeResults = await Client.getEntries({
content_type: 'competitors'
});
console.log(shipTypeResults);
const shipTypes = shipTypeResults.items.map((data) => data.fields);
const logoMap = shipTypes.reduce((acc, type) => {
return {
...acc,
[type.name]: type.images.fields.file.url
};
}, {});
console.log({ shipTypes });
this.setState({
logoMap
});
}
componentDidUpdate(prevProps, prevState) {
if (this.state.type !== prevState.type) {
}
}
componentWillUnmount() {
clearInterval(this.countdownInterval);
}
async updateRequest() {
const url = 'http://localhost:3001/hello';
console.log(url);
const fetchingData = await fetch(url);
const ships = await fetchingData.json();
console.log(ships);
this.setState({
buttonEnabled: false,
buttonClickedAt: new Date(),
progress: 0,
ships
});
setTimeout(() => {
this.setState({ buttonEnabled: true });
});
}
render() {
return (
<div className="google-map">
<GoogleMapReact
bootstrapURLKeys={{ key: 'KEY' }}
center={{
lat: this.props.activeShip ? this.props.activeShip.latitude : 42.4,
lng: this.props.activeShip ? this.props.activeShip.longitude : -71.1
}}
zoom={8}
>
</GoogleMapReact>
</div>
);
}
}
What I have done so far:
A good way would be using a setTimeout() but would that be correct? Where should that be applied and how?
setTimeout(function () {
location.reload();
}, 60 * 1000);
Or maybe setting an interval as a refresh rate?
I am a bit confused on what would the best way to approach this.

On your request function i guess u want to disable the button while the api doesn't return, so maybe move this piece above the requests:
this.setState({
buttonEnabled: false,
buttonClickedAt: new Date(),
progress: 0,
ships
});
If im wrong you could remove the timeout from the second setState and call as a callback on the first like this:
this.setState({
buttonEnabled: false,
buttonClickedAt: new Date(),
progress: 0,
ships
}, () => {
this.setState({ buttonEnabled: true });
});
on the last part instead of location.reload() set a interval calling the update on ur componentDidMount:
let updateInterval = setInterval(() => {
this.updateRequest();
}, 60 * 1000);
this.setState({updateInterval})
then on the componentWillUnmount you clear the interval this.state.updateInterval

Related

Infinte Loop in React while using navigator.geolocation.watchPosition

So I am trying to get the position of the user and store it in a React.State. I have a settings page where the user can set settings.positionAllowed to either true or false by pressing a button, false is the default value. Until pressing the button, everything works fine. But as soon as the user sets the setting to true and goes back to home page, an endless loop is created and the app crashes after some time. I first thought that the reason for this is that an instance of navigator.geolovation.watchPosition is created on every re-rendering of the component. But also the effect hook did not solve the problem.
Here is my code:
navigator.geolocation ? let posObj = {positionAllowed: false} : let posObj = {positionAllowed: true};
const [settings, setSettings] = useState(posObj);
useEffect(() => {
if(settings.positionAllowed&&navigator.geolocation){
let geolocation = navigator.geolocation.watchPosition((rawPosition)=>{
let positionData = {
positionAvailable: true,
data: rawPosition
}
if(positionData!=position){
setPosition(positionData);
}
},(err)=>{
console.log(err);
},{
enableHighAccuracy: true,
maximumAge: 10000
});
}
}
});
You need to pass [] as the second parameter of useEffect. Then, it will work like componentDidMount() in the class component. Unless, it will be called every time the state's updated, and will occur infinite loops.
navigator.geolocation ? let posObj = {positionAllowed: false} : let posObj = {positionAllowed: true};
const [settings, setSettings] = useState(posObj);
useEffect(() => {
if(settings.positionAllowed&&navigator.geolocation){
let geolocation = navigator.geolocation.watchPosition((rawPosition)=>{
let positionData = {
positionAvailable: true,
data: rawPosition
}
if(positionData!=position){
setPosition(positionData);
}
},(err)=>{
console.log(err);
},{
enableHighAccuracy: true,
maximumAge: 10000
});
}
}
}, []); // <---------------------------------
the reason for this is because your useEffect is being run every render. You need to add a dependency array. If you use a blank dependency array, it will only run on the first render.
This might help you understand it better.
[https://medium.com/better-programming/understanding-the-useeffect-dependency-array-2913da504c44][1]
navigator.geolocation ? let posObj = {positionAllowed: false} : let posObj = {positionAllowed: true};
const [settings, setSettings] = useState(posObj);
useEffect(() => {
if(settings.positionAllowed&&navigator.geolocation){
let geolocation = navigator.geolocation.watchPosition((rawPosition)=>{
let positionData = {
positionAvailable: true,
data: rawPosition
}
if(positionData!=position){
setPosition(positionData);
}
},(err)=>{
console.log(err);
},{
enableHighAccuracy: true,
maximumAge: 10000
});
}
}
}, []);

VueJs do a reload on a simple table from Vuetify

So I have a vuetify simple table that displays available times to book appointments. However, this times are pull from a database and that information get changes every 5 minutes (based on people that booked or cancel). The user will need to refresh the table to get the latest changes. Im trying to introduce some sort of auto refresh in VueJs that reloads the data every 5 minuts. this is my method that is been called right now
created(){
this.fetchAvailableTimeSlotsData75();
},
method:{
fetchAvailableTimeSlotsData75() {
this.$axios.get('appointments75', {
params: {
date: this.isCurrentMonth(this.strSelectedDate) ? '' : this.strSelectedDate,
week: this.intPageNumber
}
})
.then((objResponse) => {
if(objResponse.status == 200){
// console.log(objResponse.data)
this.total = objResponse.data.total;
this.arrAvailableDates = objResponse.data.dates;
this.arrAppointmentsData = objResponse.data.data;
this.getAppointments();
}
})
.catch((objError) => {
})
.finally(() => {
this.blnLoading = false;
this.snackbar = false
});}
}
Whats the best way to approach this in VueJs? Any Ideas?
To put it simply, use setInterval:
var _timerId;
export default {
data: () => ({
pollingInterval: 1000 * 60 * 5
}),
created() {
this.startPolling(true);
},
methods: {
startPolling(init = false) {
if (init) {
// Call it immediately
this.fetchAvailableTimeSlotsData75();
this.startPolling();
return;
}
_timerId = setInterval(this.fetchAvailableTimeSlotsData75, this.pollingInterval);
}
},
// Optional
destroyed() {
clearInterval(_timerId);
}
}

Unable to update existing document in Firebase using VUE

I have never used Firebase before this is my first stab at it using Vue.
I have a setup Firebase using Realtime Databas and set up my project so I can post using the below code in my .vue file
this.$http.post('https://MY_PROJECT_NAME.firebaseio.com/posts.json', {
title: this.blog.title,
body: this.blog.content,
createdDate: this.$options.filters.fullMthDate(this.blog.publishDate),
author: this.blog.author,
active: true,
closedDate: null,
}).then((response) => {
this.$blogAdded = true;
this.loading = false;
this.$router.push('/');
}).catch((error) => {
console.log(error);
});
The thing I can't seem to find an answer to is how to then update this document when needed (e.g. user deletes an item, I want 'active' to become false)
I went for the above code as I was using net ninjas tutorials who set FireBase up this way.
I then do a get to list all items using below in my main component
this.$http.get('https://MY_PROJECT_NAME.firebaseio.com/posts.json').then(function(data) {
return data.json();
}).then(function(data) {
var blogsArray = [];
for (let key in data) {
const date = new Date(data[key].createdDate);
const todaysDate = new Date();
if (date <= todaysDate) {
data[key].id = key
blogsArray.push(data[key])
}
}
this.blogs = blogsArray;
this.loading = false;
});
And this displays them on my site
When the user clicks the tile they go to a page where they can 'Delete/Cancel' the post and it's here I am stuck. Below is the code I am using for displaying the selected item
data() {
return {
id: this.$route.params.id,
blog: {},
loading: false,
closeModal: false,
showModal: false
};
},
beforeMount() {
this.loading = true;
},
created() {
this.$http.get('https://MY_PROJECT_NAME.firebaseio.com/posts/' + this.id + '.json').then(function(data) {
return data.json();
}).then(function(data) {
this.blog = data;
this.loading = false;
});
},
methods: {
showCloseBlogModal() {
console.log(this.blog)
VueEvent.$emit('show-delete-blog-modal', this.blog);
}
}
Then when the modal is displayed I get the following in the console.log
I need to update the 'active' value to false when they click 'Yes' using the below
methods: {
deleteBlog() {
// CODE HERE WHEN CLICK 'YES' TO CANCEL
}
}

clearInterval if pagination page is bigger than 1

i'm working on small project using Vue.js i have created a pagination system to display my database users in a table, i have a small issue, i would like to know how can i stop the setinterval if my getResult function page variable is bigger than 1.
this is my code :
data(){
return {
editMode : true,
customer_id : null,
laravelData : {},
formFields : {}
}
},
methods:{
getResults(page = 1){
axios.get('Thirdparty/loadCustomers/' + page).then(response => {
this.laravelData = response.data;
});
}
},
created(){
self = this;
setInterval(function(){
self.getResults();
}, 5000);
}
First and foremost, always capture identifiers from setInterval and setTimeout.
By capturing your interval ID you can later remove it from within your callback when the page value is larger than its default (1).
EDIT: The OP would like to be able to reset the interval when page resets.
created() {
this.resetInterval();
},
methods: {
resetInterval() {
this.currentInterval && clearInterval(this.currentInterval);
this.currentInterval = setInterval(() => this.getResults(), 5000);
},
getResults(page = 1) {
if (page == 1 && !this.currentInterval) {
this.resetInterval();
} else {
clearInterval(this.currentInterval);
}
axios.get('Thirdparty/loadCustomers/' + page).then(response => {
this.laravelData = response.data;
});
}
}
data(){
return {
editMode : true,
customer_id : null,
laravelData : {},
formFields : {},
currentInterval : null
}
},
methods:{
getResults(page = 1){
clearInterval(this.currentInterval);
axios.get('Thirdparty/loadCustomers/' + page).then(response => {
this.laravelData = response.data;
});
},
created(){
self = this;
self.currentInterval = setInterval(function(){
self.getResults();
}, 5000);
}

On Touchable highlights add componant

I want to add exported component on TouchableHighlight in react-native.
var MessageBox = require('./GiftedMessengerContainer');
var MyAppName = React.createClass({
_openGiftedMessanger(){
return (<MessageBox style={styles.container}/>);
},
render: function() {
return (
<View style={styles.container}>
<TouchableHighlight
style={styles.imButton}
onPress={this._openGiftedMessanger}>
<Text>Open Chat Room</Text>
</TouchableHighlight>
}
</View>
);
}
AppRegistry.registerComponent('MyAppName', () => AppName);
And my module is,
import React, {
Linking,
Platform,
ActionSheetIOS,
Dimensions,
View,
Text,
//Navigator,
Component,
} from 'react-native';
var GiftedMessenger = require('react-native-gifted-messenger');
var Communications = require('react-native-communications');
// var STATUS_BAR_HEIGHT = Navigator.NavigationBar.Styles.General.StatusBarHeight;
// if (Platform.OS === 'android') {
// var ExtraDimensions = require('react-native-extra-dimensions-android');
// var STATUS_BAR_HEIGHT = ExtraDimensions.get('STATUS_BAR_HEIGHT');
// }
class GiftedMessengerContainer extends Component {
constructor(props) {
super(props);
this._isMounted = false;
this._messages = this.getInitialMessages();
this.state = {
messages: this._messages,
isLoadingEarlierMessages: false,
typingMessage: '',
allLoaded: false,
};
}
componentDidMount() {
this._isMounted = true;
setTimeout(() => {
this.setState({
typingMessage: 'React-Bot is typing a message...',
});
}, 1000); // simulating network
setTimeout(() => {
this.setState({
typingMessage: '',
});
}, 3000); // simulating network
setTimeout(() => {
this.handleReceive({
text: 'Hello Awesome Developer',
name: 'React-Bot',
image: {uri: 'https://facebook.github.io/react/img/logo_og.png'},
position: 'left',
date: new Date(),
uniqueId: Math.round(Math.random() * 10000), // simulating server-side unique id generation
});
}, 3300); // simulating network
}
componentWillUnmount() {
this._isMounted = false;
}
getInitialMessages() {
return [
{
text: 'Are you building a chat app?',
name: 'React-Bot',
image: {uri: 'https://facebook.github.io/react/img/logo_og.png'},
position: 'left',
date: new Date(2016, 3, 14, 13, 0),
uniqueId: Math.round(Math.random() * 10000), // simulating server-side unique id generation
},
{
text: "Yes, and I use Gifted Messenger!",
name: 'Awesome Developer',
image: null,
position: 'right',
date: new Date(2016, 3, 14, 13, 1),
uniqueId: Math.round(Math.random() * 10000), // simulating server-side unique id generation
},
];
}
setMessageStatus(uniqueId, status) {
let messages = [];
let found = false;
for (let i = 0; i < this._messages.length; i++) {
if (this._messages[i].uniqueId === uniqueId) {
let clone = Object.assign({}, this._messages[i]);
clone.status = status;
messages.push(clone);
found = true;
} else {
messages.push(this._messages[i]);
}
}
if (found === true) {
this.setMessages(messages);
}
}
setMessages(messages) {
this._messages = messages;
// append the message
this.setState({
messages: messages,
});
}
handleSend(message = {}) {
// Your logic here
// Send message.text to your server
message.uniqueId = Math.round(Math.random() * 10000); // simulating server-side unique id generation
this.setMessages(this._messages.concat(message));
// mark the sent message as Seen
setTimeout(() => {
this.setMessageStatus(message.uniqueId, 'Seen'); // here you can replace 'Seen' by any string you want
}, 1000);
// if you couldn't send the message to your server :
// this.setMessageStatus(message.uniqueId, 'ErrorButton');
}
onLoadEarlierMessages() {
// display a loader until you retrieve the messages from your server
this.setState({
isLoadingEarlierMessages: true,
});
// Your logic here
// Eg: Retrieve old messages from your server
// IMPORTANT
// Oldest messages have to be at the begining of the array
var earlierMessages = [
{
text: 'React Native enables you to build world-class application experiences on native platforms using a consistent developer experience based on JavaScript and React. https://github.com/facebook/react-native',
name: 'React-Bot',
image: {uri: 'https://facebook.github.io/react/img/logo_og.png'},
position: 'left',
date: new Date(2016, 0, 1, 20, 0),
uniqueId: Math.round(Math.random() * 10000), // simulating server-side unique id generation
}, {
text: 'This is a touchable phone number 0606060606 parsed by taskrabbit/react-native-parsed-text',
name: 'Awesome Developer',
image: null,
position: 'right',
date: new Date(2016, 0, 2, 12, 0),
uniqueId: Math.round(Math.random() * 10000), // simulating server-side unique id generation
},
];
setTimeout(() => {
this.setMessages(earlierMessages.concat(this._messages)); // prepend the earlier messages to your list
this.setState({
isLoadingEarlierMessages: false, // hide the loader
allLoaded: true, // hide the `Load earlier messages` button
});
}, 1000); // simulating network
}
handleReceive(message = {}) {
// make sure that your message contains :
// text, name, image, position: 'left', date, uniqueId
this.setMessages(this._messages.concat(message));
}
onErrorButtonPress(message = {}) {
// Your logic here
// re-send the failed message
// remove the status
this.setMessageStatus(message.uniqueId, '');
}
// will be triggered when the Image of a row is touched
onImagePress(message = {}) {
// Your logic here
// Eg: Navigate to the user profile
}
render() {
return (
<GiftedMessenger
ref={(c) => this._GiftedMessenger = c}
styles={{
bubbleRight: {
marginLeft: 70,
backgroundColor: '#007aff',
},
}}
autoFocus={false}
messages={this.state.messages}
handleSend={this.handleSend.bind(this)}
onErrorButtonPress={this.onErrorButtonPress.bind(this)}
maxHeight={Dimensions.get('window').height} //- Navigator.NavigationBar.Styles.General.NavBarHeight - STATUS_BAR_HEIGHT}
loadEarlierMessagesButton={!this.state.allLoaded}
onLoadEarlierMessages={this.onLoadEarlierMessages.bind(this)}
senderName='Awesome Developer'
senderImage={null}
onImagePress={this.onImagePress}
displayNames={true}
parseText={true} // enable handlePhonePress, handleUrlPress and handleEmailPress
handlePhonePress={this.handlePhonePress}
handleUrlPress={this.handleUrlPress}
handleEmailPress={this.handleEmailPress}
isLoadingEarlierMessages={this.state.isLoadingEarlierMessages}
typingMessage={this.state.typingMessage}
/>
);
}
handleUrlPress(url) {
Linking.openURL(url);
}
// TODO
// make this compatible with Android
handlePhonePress(phone) {
if (Platform.OS !== 'android') {
var BUTTONS = [
'Text message',
'Call',
'Cancel',
];
var CANCEL_INDEX = 2;
ActionSheetIOS.showActionSheetWithOptions({
options: BUTTONS,
cancelButtonIndex: CANCEL_INDEX
},
(buttonIndex) => {
switch (buttonIndex) {
case 0:
Communications.phonecall(phone, true);
break;
case 1:
Communications.text(phone);
break;
}
});
}
}
handleEmailPress(email) {
Communications.email(email, null, null, null, null);
}
}
module.exports = GiftedMessengerContainer;
How to add custom views on my screen?
You need to make use of something called as states (in React terms). When onPress function is invoked you set a state variable to open/close which then can be used to show/hide the custom view. For ex:
var MessageBox = require('./GiftedMessengerContainer');
var MyAppName = React.createClass({
getInitialState: function(){
return {
messageBoxShow: 'false'
}
},
_openGiftedMessanger:function(){
this.setState({
messageBoxShow: 'true'
});
},
render: function() {
return (
<View style={styles.container}>
<TouchableHighlight
style={styles.imButton}
onPress={this._openGiftedMessanger}>
<Text>Open Chat Room</Text>
</TouchableHighlight>
{this.state.messageBoxShow === 'true' ? <MessageBox style={styles.container}/> : null };
</View>
);
}
AppRegistry.registerComponent('MyAppName', () => AppName);

Categories