React function loose state on second try - javascript

this code works properly on first and third try, there's always a step where it bugs and send no data to the db, it ruin my business logic every time, I tried with and without page reload got the same results
apiCall = e => {
e.preventDefault();
window.scrollTo(0, 0);
this.setState({ loading: true });
const { currentUser } = fire.auth();
let userEmail = currentUser.email;
let userUnderscore = userEmail.replace(/\./g, '_');
let intervalMS = this.state.interval * 60000;
let url = `https://url.com/api/v1/${userUnderscore}/${this.state.urlTask}?url=${this.state.urlTask}&width=${this.state.width}&interval=${intervalMS}&user=${userUnderscore}&running=true`;
if (this.state.interval >= 1 && this.state.urlTask !== "") {
fetch(url)
}
else {
this.setState({ addURLError: true, loading: false });
}
this.setState({ addURL: true, addURLError: false });
fire.database().ref(`/master/users/${userUnderscore}/setup/`)
.update({
running: true,
interval: this.state.interval,
url: this.state.urlTask,
});
setTimeout(
function () {
this.setState({ addURL: false, running: true });
window.location.reload();
}.bind(this), 2000
);
}
...
<Button color='black' onClick={this.apiCall} animated='vertical' type='submit'>
EDIT
The function and the db actually get updated, the issue is that on second try the state is empty even if the form hold values

I fixed the issue by reloading the app before any attempt of executing the function, that way there's always a fresh state to be used : window.location.reload();

Related

Not able to perform 2 actions on the same component when hardware back button is pressed in react-native,below are the code regarding the backhandler

backAction = () => {
if (this.props.navigation.isFocused() && !this.state.otpScreen) {
this.setState({ showLoginScreen: true });
return true;
} else if(this.state.showLoginScreen) {
this.props.navigation.dispatch(CommonActions.reset({
index: 0,
routes: [
{ name: 'Login' },
],
}))
return false;
}
};
the code above is for action that should be done by the hardware back press, at first it should show the one screen and on the second press it should exit the app, both otp screen and login screen are on the same component, I'm just hiding based on the condition ...
at the first time it is working as per the condition but for the second time it's not.
componentDidMount() {
this.focusListener = this.props.navigation.addListener('focus', () => {
this.setState({
mobile: '',
showLoginScreen: true,
});
});
this.getDataFromStorage();
AsyncStorage.setItem('countryCode', '+91');
BackHandler.addEventListener(
"hardwareBackPress",
this.backAction
);
}
componentWillUnmount() {
clearInterval(this.interval)
BackHandler.addEventListener('hardwareBackPress', () => { return false })
}
can anyone pls help me how to do this,thanks in Advance
I guess your problem is that you can't access the 'current' value of a state inside a listener.
More Details here
Try to use a Reference instead of a state

Infinite scroll vuejs fired more than once

I'm trying to implement an infinite scroll in my vue chrome extension. I have this code but the problem is that when the page bottom is reached, the ajax call to fetch new data is fired more than once. How i can fix?
mounted() {
this.$store.commit('preloader', false)
window.onscroll = () => {
if( window.scrollY + window.innerHeight >= document.body.scrollHeight ){
console.log('fired')
this.nextPageLoaded = false
this.nextPage()
}
}
},
methods: {
nextPage() {
console.log('Loading next page')
axios.get('https://localhost:8080/api/media')
.then( (response) => {
console.log(response.data)
this.$store.commit('profileMedia', response.data.media)
this.nextPageLoaded = true
})
}
}
I've tried by setting a variable nextPageLoad to true after data are loaded and on false when the scroll event reach the bottom but not work as expected. Any solution will be appreciaetd
Perhaps it's a typo but I don't see that you are actually using the nextPageLoaded property as a flag in the if statement.
It should be something like
mounted() {
this.$store.commit('preloader', false)
window.onscroll = () => {
if ( (window.scrollY + window.innerHeight >= document.body.scrollHeight)
&& !this.nextPageLoaded) {
console.log('fired')
this.nextPageLoaded = true
this.nextPage()
}
}
},
methods: {
nextPage() {
console.log('Loading next page')
axios.get('https://localhost:8080/api/media')
.then( (response) => {
console.log(response.data)
this.$store.commit('profileMedia', response.data.media)
this.nextPageLoaded = false
})
}
}
Also have in mind that I switched the values of the nextPageLoaded property assignments because I think it's more intuitive this way (assigns to true immediately after triggering the nextPage method, assigns to false after ending the AJAX call).

Laravel vue infinite scroll won't pull new data

I am using element UI and it has infinite scroll with it, but i can't get it to work in my app.
Code
script
data() {
return {
count: '', // default is 8
total: '', // defalt is 15
perPage: '', // default is 8
loading: false,
products: [],
}
},
computed: {
noMore () {
return this.count >= this.total // if this.count (8) reach this.total (15) then show no more text.
},
disabled () {
return this.loading || this.noMore
}
},
methods: {
load () {
this.loading = true
setTimeout(() => {
this.count += this.perPage // add 8 more to page
this.loading = false
}, 1000)
},
getProducts: function(){
axios.get('/api/products').then(response => {
this.products = response.data.data;
this.count = response.data.meta.per_page; // set count to 8 (backend based)
this.perPage = response.data.meta.per_page; // set perPage to 8 (backend based)
this.total = response.data.meta.total; // my testing data are 15 so it sets total to 15 (backend based)
}).catch((err) => console.error(err));
}
},
mounted() {
this.getProducts();
}
HTML
<div class="row mt-5 my-5 infinite-list" v-infinite-scroll="load" infinite-scroll-disabled="disabled"> // load function
<div class="col-md-3 mb-3" v-for="product in products" :key="product.slug" :offset="1"> // loop function
<el-card shadow="hover" :body-style="{ padding: '0px' }">
{{product.name}}
</el-card>
</div>
// infinite functions
<div class="col-md-12 mt-3" v-if="loading">
<el-card shadow="always" class="text-center">Loading...</el-card>
</div>
<div class="col-md-12 mt-3" v-if="noMore">
<el-card shadow="always" class="text-center">That's it, No more!</el-card>
</div>
</div>
Meta data
Result
What did I do wrong in my code?
its because of your load function take look on it,
load () {
this.loading = true
setTimeout(() => {
this.count += this.perPage // add 8 more to page
this.loading = false
}, 1000)
},
you have set time out for 1000 ms which is called after each scroll
first count is updated by fetch call and then second time its updated by time out call back of load function ,
instead of making this.loading =false after 1000 ms you should make it false on success of fetch call and same thing apply for updating this.count, hope this will help you.
EDIT:
your load function should be like following
load () {
this.loading = true
this.getProducts();//previously you getproduct is called once only after mounted,you you need to call it each time whenever load is called
},
and you fetch function should be like
getProducts: function(){
axios.get('/api/products').then(response => {
this.products = response.data.data;
this.count += this.perPage // add 8 more to page
this.loading = false
this.perPage = response.data.meta.per_page; // set perPage to 8 (backend based)
this.total = response.data.meta.total; // my testing data are 15 so it sets total to 15 (backend based)
}).catch((err) => console.error(err));
}
another thing you can try is ,use getProducts instead of load and remove load function, make this.loading=true in your getProducts function,
previously your getProducts is called only once when component is mounted.you need to call getProducts function each time whenever load more is requested.

such empty alert with jsx / react alternatives

So I was thinking I found a great way to alert users that the array is empty and there's nothing to display but actually my technique is not well implemented and only works onFocus or page reload, I put the function on componentDidMount()
componentDidMount = () => {
this.setState({loading: true})
const { currentUser } = fire.auth();
fire.database().ref(`/master/${currentUser.uid}/feed/sponsors/`)
this.setState({
sponsorsList:sponsorsList,
}, () => {
if (this.state.sponsorsList.length === 0)
this.setState({loading: false, empty: true})
});
});
}
This works but such empty text in the view still appears after I push something to the array, how do I trigger that .length function ?
{this.state.empty ? <h6 class='mb-3'>Such empty!</h6> : null }
Please someone suggest a better alternative.
I think you need to add else logic:
if (this.state.sponsorsList.length === 0) {
this.setState({ loading: false, empty: true })
} else { // Here are the additions
this.setState({ loading: false, empty: false })
}
Oh, then you can write:
{this.state.empty && <h6 class="mb-3">Such empty!</h6>}
Hope it helps :)

Redirect after the flash message disappears in Angular2

I have a function which calls a service.
submitPost(value:any)
{
this._adminLogin.postAdminLogin(this.adminLoginmodel).subscribe(
data => {
this.responseStatus = data;
if(this.responseStatus.status == 1)
{
localStorage.setItem('admin_id', this.responseStatus.detail.id);
this._flashMessagesService.show(this.responseStatus.message, { cssClass: 'alert-success', timeout: 5000 });
top.location.href = 'admin/dashboard';
}
else
{
this._flashMessagesService.show(this.responseStatus.message, { cssClass: 'alert-danger', timeout: 2000 });
}
},
err => {
console.log(err)
},
() => {}
);
this.status = true;
}
My concern is with this section of code:-
if(this.responseStatus.status == 1)
{
localStorage.setItem('admin_id', this.responseStatus.detail.id);
this._flashMessagesService.show(this.responseStatus.message, { cssClass: 'alert-success', timeout: 5000 });
top.location.href = 'admin/dashboard';
}
Is there any way by which the redirect action could take place after the flash message disappears after 5000 ms? Something like this:-
if(this.responseStatus.status == 1)
{
localStorage.setItem('admin_id', this.responseStatus.detail.id);
this._flashMessagesService.show(this.responseStatus.message, { cssClass: 'alert-success', timeout: {function(){ top.location.href = 'admin/dashboard'; }, 5000 });
}
The following code should navigate after the message disappears. Yout flashMessage will be displayed for 5000 ms and your navigate should happen after 7000ms
if(this.responseStatus.status == 1)
{
localStorage.setItem('admin_id', this.responseStatus.detail.id);
this._flashMessagesService.show(this.responseStatus.message, { cssClass: 'alert-success', timeout: 5000 });
setTimeout(()=>{
top.location.href = 'admin/dashboard';
},7000);
}
I would do this by having the _flashMessagesService.show() return an Observable.
In the _flashMessageService, something like this:
myObserver : Observer<any>
function show(){
// do stuff
return Observable.create(observer =>{
this.myObserver =observer;
});
}
When you're ready to resolve the Observable, you can do:
this.myObserver.next('Possibly some value here');
this.myObserver.complete();
In your invoking code
this._flashMessagesService.show()
.subscribe(result=> { top.location.href = 'admin/dashboard'});}
I have been working on something similar.
An alternate approach, perhaps simpler is to just use Observable.timer in your main component:
Observable.timer(5000).subscribe(result=> { top.location.href = 'admin/dashboard'});
I prefer the first way, because it is contingent on the flashMessage service deciding when the flash message goes away, not on a hard coded time value.

Categories

Resources