Data VS Async Data in Nuxt - javascript

Im using vue.js with nuxt.js, I'm just still confused as when to use Data VS Async Data. Why would I need to use Async data when I just have data that just displays on the page?
I have a data object of FAQ's and just want to display the data without doing anything with it. What are the benefits of using the asyncData? Or what are the cases or best use of them?
Should I display list data such as this as async by default if using data such as this inside of my component?
Data
data:() => ({
faqs:[
{"title":"faq1"},
{"title":"faq2"},
{"title":"faq3"},
]
}),
asyncData
asyncData(context) {
return new Promise((resolve, reject) => {
resolve({
colocationFaqs:[
{"title":"faq1"},
{"title":"faq2"},
{"title":"faq3"},
]
});
})
.then(data => {
return data
})
.catch(e => {
context.error(e);
});
},

asyncData happes on the serer-side. You cant access browser things like localStorage or fetch() for example but on the ther hand you can access server-side things.
So why should you use asyncData instead of vue cycles like created?
The benefit to use asyncData is SEO and speed. There is this special context argument. It contains things like your store with context.store. Its special because asyncData happens on server-side but the store is on the client side usually. That means you can get some data and then populate your store with it and somewhere else you display it. The benefit of this is that its all server-side and that increase your SEO so for example the google crawler doesnt see a blank page
why would I need to pre render it when it is going to be displayed
anyway
Yes for us it doesnt matter if i send 1 File to the client and it renders all data like in SPA's or if its pre-rendered. But it doesnt matter for the google crawler. If you use SPA mode the crawler just sees a blank page. You can discoverd it too. Go to any SPA website and click right-click and inspect you will see thats there only 1 Div tag and few <script> tags. (Dont press F12 and inspect like this thats not what i mean).

Related

How to have a 'placeholder' or Home Screen without API call on page landing?

I would like wisdom again.
I am making a single page application with quite a bit of AXIOS calls, as you can see here.
useEffect(() => {
axios.all([
axios.request(options),
axios.request(optionsQuote),
axios.request(optionsDaily),
axios.request(optionsNews)
],)
.then(response => {
setData(response)
})
console.log(data);
}, [tix])
My conundrum is that this runs every time I land on the page (for obvious reasons) and have to have an initial data in order for the app to run.
const [tix, setTix] = useState('AAPL')
I want to be able to land on a 'placeholder' type data, so to avoid the first initial call and only call when user searches and clicks on the company name, data. This function works fine after the page lands and initial stock (AAPL) is called. I want to not call it.
The problem is, I am trying to make a single page web app and would like to avoid using routes, if possible.
If I leave the initial state as blank (''), than, the code breaks since all of my data is derived from the fact that "data" has data in it.
const [data, setData] = useState(null)
Is the only way for me to get initial page without data showing is to make another component (such as 'landingPage')? If so, how do I go about doing that?

Is there any way to cache the API response in VueJS

In our VueJS application, we are having few API's which are calling each and every time whenever the page reloads. In those API's. few response will never change and very few will rarely change. I planning to cache those API calls response and store it in a variable and use it whenever needed and reduce the number of requests when page reloads.
I am new to vueJS and not having any idea how to implement it. Is there anyway to achieve this in VueJS or Javascript? Any help would be most appreciated.
Sample HTML code,
<div class="col-sm-6">
<span>Is User Available? {{userInfo[is_user_available]}} </span>
<span> User Type : {{userType}} </span>
</div>
API call will be like below,
created: function () {
this.checkForUser();
},
methods: {
checkForUser: function() {
this.api.call('user_info', { username : this.username })
.then((response) => {
if (response) {
this.userInfo = response;
this.userType = this.userInfo['user_type'];
}
})
.catch((error) => {
this.userInfo.length = 0;
})
}
}
If you store the data in a regular Vuex store you will loose it on page refresh unless you use vuex-persistedstate plugin, which saves the store data on the local storage. (here is a working example)
Elaborating on #Mysterywood answer you can simply store it on local storage by yourself.
You can achieve that by simply doing
get:
const userType = window.localStorage.getItem('userInfo')
set:
window.localStorage.setItem('userInfo', response)
and remove:
window.localStorage.removeItem('userInfo')
There are few ways of doing this depending on how deep you want to go:
If you just want state to persists during the SPA session, you can do so:
Vuex if you would like to store globally accessible state/data. This allows your state to persist regardless of whether the components are destroyed/created.
Store it on your root-level Vue instance. If you're using the Vue CLI, this will be in your main.js. You can do something like so:
new Vue({
// ...
data: {
userType: {}
}
})
You can then access it via this.$root.userType. This is fine for small projects, but generally not recommended as things can get messy very quickly.
There's also EventBus, but again, this can get messy very quickly. EventBus is also deprecated in Vue3.
If you want to cache the response and access them again even after the user close their tab/browser, you will want to look into:
Cookies
localStorage
ServiceWorkers
check this, it can help :client-side storage in vuejs
Client-side storage is an excellent way to quickly add performance gains to an application. By storing data on the browser itself, you can skip fetching information from the server every time the user needs it. While especially useful when offline, even online users will benefit from using data locally versus a remote server. Client-side storage can be done with cookies, Local Storage (technically “Web Storage”), IndexedDB, and WebSQL (a deprecated method that should not be used in new projects).

Design issue using document.addEventListener('DOMContentLoaded',

I am learning how to create a simple CRUD Node Express Web Application using APIs.
When my index.js page loads I have a default html table which displays a record of data populated within the Function:
document.addEventListener('DOMContentLoaded', function () {
fetch('http://localhost:3000/getQuestion/+ID)
.then(response => response.json())
.then(data => loadHTML(data['data']));
});
Inside this function I made a Get API call to return the data which populates the table with a record stored in my Database.
I run into a problem when I want to update this table with the next record. When I get the next record, I increment my ID by 1.
But in order to display the new record into the table, I have to also perform a location.reload() to refresh the content within the table with the new data; This in turn clears out my ID indexes.
My questions are:
Where is the correct place within a js file to display the table data for my html table. Does it make sense to put it in: document.addEventListener('DOMContentLoaded function ?
If so, then every time this table data changes I have to call a page refresh. Is this correct?
Doing the page refresh clears out all my variables that are used to populate the parameters of my APIs
Where am I going wrong here.
Where is the correct place within a js file to display the table data for my html table. Does it make sense to put it in: document.addEventListener('DOMContentLoaded function ?
Yes and no. DOMContentLoaded is almost never needed outside library development. Instead, to make your code run only after the page has been parsed and the DOM built, do one of these things:
Use a module rather than a script (<script type="module" ...>) if your target browsers support it; or
Use defer on your non-module script tag; or
Put your non-module script tag at the end of the HTML, just before the closing </body> tag
If you do any of those things, your page's DOM is ready to be manipulated by your code by the time your code runs and you could just do the fetch without wrapping it in an event. Using a module also has the benefit that your top-level variables aren't globals and module code is always in strict mode.
But doing it in a DOMContentLoaded handler is fine too.
If so, then every time this table data changes I have to call a page refresh. Is this correct?
There are other ways to change or add to the table data. You haven't shown loadHTML, but you can use appendChild on the table or tbody element, insertAdjacentHTML, insertAdjacentText, etc. More on MDN.
Doing the page refresh clears out all my variables that are used to populate the parameters of my APIs
Yes, refreshing the page completely resets the global environment and all nested environments, so everything on the page is refreshed.
Side note: There are two minor problems with the fetch code you've shown:
I'm afraid it's falling prey to the fetch API footgun. fetch only rejects its promise on network error, not HTTP error. So a 404, 500, etc., doesn't reject the promise. You have to check for HTTP success explicitly (which is why I always use a wrapper function).
You're not handling errors.
To fix both:
fetch('http://localhost:3000/getQuestion/+ID)
.then(response => {
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response.json();
})
.then(data => loadHTML(data['data']))
.catch(error => {
// Handle/report error
});

How is this fetch optimised on react gatsby website

On the front page of a website served with a Gatsby React setup I have a NavbarExtra component that shows some data via an api. The data coming from that endpoint changes several times a day.
The idea now is now to optimize the fetch so the fetch is made as seldom as possible so the api is used as rearly as possible, it has a limit to it(different paid plans).
The scenario should be that as long as the user has entered the site the fetch will only happen at once. Then the user can go around the site maybe close even the component with the fetch and again go back to the front-page where the fetch is made.
Now the component is called in the navmenu if the user is only on the front page:
{isLandingPage && <NavBarData/>} and in that component there is this fetch:
useEffect(() => {
fetch(
'https://endpoint',
{
method: 'GET',
headers: {
},
}
)
.then(response => {
if (response.status >= 200 && response.status <= 299) {
return response.json();
}
throw Error(response.statusText);
})
.then(data => {
const { result } = data.quoteResponse;
setNumbers(result));
})
.catch(error => {
console.log(error);
});
}, 0);
Firstly I would like to ask for how should this fetch be done so the api is used as rearly as possible, so the user gets the recent data and only gets it again when for example reloading the page?
Secondly I understand some concepts about single page apps and static site generators as here the used Gatsby, and probably have understood it right that if I would like to use the fetched data on different pages(even other pages than the isLandingPage) of the website I could just use it in one component that is served on different pages and it would not refetch on each page enter?
You could create a Parent component that fetches the data and can retrieve the data to the childrens, so you only control the fetch in one component only one time on each session, or wherever you need it. In this case depending on you architechture you could use simple stateor the context API to reuse this data on several and nested components.
Other solution could involve using the localStorage, so you could store the data fetched on the localStorage and reuse this data on any component, you just will have to update the data when you need it.

Trying to hit an API with JSON data in REACT

I have just started learning to code in ReactJS and have come to the part where I need to hit an API to get back JSON data.
I am running this on a node server on my local which tries to build it each time I make a change - this helps because it shows me where my errors are. Unfortunately it doesn't mean I know why I am getting an error.
This is my code so far:
import React from 'react';
import './App.css';
var GetUnassignedClients = React.createClass({
unassignedClients: function () {
return $.getJSON('http://localhost/backoffice/?action=unassignedClients.getUnassingedClients')
.then((data) => {
this.setState({resultMe: data.results});
});
},
render: function() {
return (
<div>this.state.resultMe</div>
);
}
});
module.exports = GetUnassignedClients;
I will re-paste the bit that seems to be throwing the error:
return $.getJSON('http://localhost/backoffice/?action=unassignedClients.getUnassingedClients')
.then((data) => {
this.setState({resultMe: data.results});
});
The error seems to be pointing at the $ - when I wrap this all in {} then it points to the full stop (.).
Not sure if I am doing something wrong or missing something.
The $in the $.getJSON is referring to jQuery. Do you have it included in your page? Javascript is trying to parse the dollar sign and can't find it. Other possible solution is to use a separate http library (if you don't need jQuery), such as axiois or fetch for example.
Im not sure, but I thought you would hit in this way
fetch(`http://localhost:8088/api/this/is/an/api/call`)
.then(result=> {
this.setState({items:result.json()});
});
Okay turns out I was trying to use $.getJSON which is JQuery - due to building this on my local using a node server JQuery wasn't included on my local development before the production code was built.
So instead I looked into using fetch that seems to be the go to when coding in react.
I also moved this section into a componentDidMount function so the app would be loaded and then the API call would be made - not that I have a lot of data to load but it's good practice for when you do.
My working code for this section:
componentDidMount () {
fetch("http://localhost/dashboard/?action=unassignedUsers.getUnassingedUsers", {
credentials: 'same-origin'
})
.then(response => response.json())
.then(json => this.setState({data: json}));
}
I also came across a couple issues using fetch - if you need a session available to access said data then you need to specifically pass through the credentials or the API call will re-direct to the login page. At first I saw a status 200 but no data - as it successfully re-directed to the login page, but obviously there was no JSON to access here.

Categories

Resources