GeodooBlog App Development Series with React Native
GeodooBlog: refactoring the api call to include number of posts and pages
Hi there! How are you? I hope you are well!
Well, today we are gonna jot down a couple of things, more like the steps of the thought process that led to a good enough solution in my opinion to the problem of having some kind of variable so we know if we have loaded all posts of all pages! Here is the code with all its transforms.
The api object
In the api object we have the asynchronous HTTP calls to the WP REST API which return Promises. The main objective this time was to somehow manage to pass the variable of the total pages of posts to our state object! Here is the code before our solution (maybe in the future will be changed again, especially if we introduce Redux for handling the state of our app):
const api = { fetchSiteInfo() { let url = 'https://geodoo.work/wp-json'; return fetch(url).then((res) => res.json()); }, fetchPosts() { let url = 'https://geodoo.work/wp-json/wp/v2/posts'; return fetch(url).then((res) => res.json()); } }; export default api; // TODO // console.log(res.headers.map['x-wp-total'][0]); // console.log(res.headers.map['x-wp-totalpages'][0]);
You can see that even the function are very similar. Although we could refactor this code too, we did something else. We delayed the json for inside the Component’s function, so we can pass it to the state easily. The code after:
const api = { fetchSiteInfo() { let url = 'https://geodoo.work/wp-json'; return fetch(url).then((res) => res.json()); }, fetchPosts() { let url = 'https://geodoo.work/wp-json/wp/v2/posts'; return fetch(url); } }; export default api;
The MainScreen getPostsFromApi function
So, inside the Component this time we did something like the following. Code before:
_getPostsFromApi() { api.fetchPosts() .then((json) => { this.setState({ posts: json, animating: !this.state.animating }) }) .catch((error) => { console.error(error) }) }
There was a middle step here in my thought process. So, let’s call it Stage 1:
_getPostsFromApi() { api.fetchPosts() .then((res) => { const totalPages = res.headers.map['x-wp-totalpages'][0] const totalNumberOfPosts = res.headers.map['x-wp-total'][0] this.setState({ totalPages, totalNumberOfPosts }) return res.json() }) .then((json) => { this.setState({ posts: json, animating: !this.state.animating }) }) .catch((error) => { console.error(error) }) }
Finally, the code after ended up like this avoiding the DOUBLE call to setState() and therefore the rerendering of the Component unnecessarily twice:
getPostsFromApi() { let totalPages, totalNumberOfPosts api.fetchPosts() .then((res) => { totalPages = res.headers.map['x-wp-totalpages'][0] totalNumberOfPosts = res.headers.map['x-wp-total'][0] return res.json() }) .then((json) => { this.setState({ posts: json, animating: !this.state.animating, totalPages, totalNumberOfPosts }) }) .catch((error) => { console.error(error) }) }
The state object (initially)
Now, we hold another two pieces of information to our state object. The code before:
state = { posts: [], animating: true }
Code after:
state = { posts: [], animating: true, totalPages: 0, totalNumberOfPosts: 0 }
I hope you got a clear picture of the thought process and the refactoring of our state object. If you can find sth better at this point, please share with me or make a pull request in my repo.
Thanks
and Cheers!