Having a frustrating issue, hope someone can help. for full repo available at https://github.com/georgecook92/Stir/blob/master/src/components/posts/viewPosts.jsx.
Get straight into the code -
componentDidMount() {
const {user_id,token} = this.props.auth;
this.props.startLoading();
console.log('props auth', this.props.auth);
if (user_id) {
console.log('user_id didMount', user_id);
this.props.getUserPosts(user_id, token);
}
}
If the component is loaded through the ui from another component it functions as expected. However, if the page is refreshed user_id etc is not available immediately to componentDidMount.
I have checked and it is available later on, but I found that if I move my AJAX call to get the posts to a render method or other lifecycle method like componentWillReceiveProps - the props are being updated constantly and it locks the UI - not ideal.
I am also unsure as to why multiple ajax calls per second are being made if I move the ajax call to the render method.
I hope you can help! Thank you.
Edit.
export function getUserPosts(user_id, token){
return function(dispatch) {
if (window.indexedDB) {
var db = new Dexie('Stir');
db.version(1).stores({
posts: '_id, title, user_id, text, offline',
users: 'user_id, email, firstName, lastName, token'
});
// Open the database
db.open().catch(function(error) {
alert('Uh oh : ' + error);
});
db.posts.toArray().then( (posts) => {
console.log('posts:', posts);
if (posts.length > 0) {
dispatch( {type: GET_POSTS, payload: posts} );
}
});
}
axios.get(`${ROOT_URL}/getPosts?user_id=${user_id}`, {
headers: {
authorisation: localStorage.getItem('token')
}
}).then( (response) => {
console.log('response from getPosts action ', response);
dispatch( {type: GET_POSTS, payload: response.data} );
dispatch(endLoading());
response.data.forEach( (post) => {
if (post.offline) {
if (window.indexedDB) {
db.posts.get(post._id).then( (result) => {
if (result) {
//console.log('Post is already in db', post.title);
} else {
//console.log('Post not in db', post.title);
//useful if a posts offline status has changed
db.posts.add({
_id: post._id,
title: post.title,
user_id: post.user_id,
text: post.text,
offline: post.offline
});
}
} )
}
}
} );
})
.catch( (err) => {
console.log('error from get posts action', err);
if (err.response.status === 503) {
dispatch(endLoading());
dispatch(authError('No internet connection, but you can view your offline posts! '));
} else {
dispatch(endLoading());
dispatch(authError(err.response.data.error));
}
});
}
}
I would suggest using componentWillReceiveProps and saving your props as state to trigger a re-render if a change occurs (ex. a prop changes from undefined to having a value). Something like this will work:
import React, {Component} from 'react';
// using lodash for checking equality of objects
import _isEqual from 'lodash/isEqual';
class MyComponent extends Component {
constructor(props={}) {
super();
this.state = props;
}
// when the component receives new props, like from an ajax request,
// check to see if its different from what we have. If it is then
// set state and re-render
componentWillReceiveProps(nextProps) {
if(!_isEqual(nextProps, this.state)){
this.setState(nextProps);
}
}
render() {
return (
<div>{this.state.ItemPassedAsProp}</div>
);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With