Data fetching with nextjs 'catch all' routes - reactjs

With nextjs 10, you can have a catch all route, which looks something like this [...id].tsx. The idea is that this will allow for dynamic pages. So it should match /example, /example/new, /example/new/latest etc.
The issue im facing is that a specific matched routes (for example /example/new) may need extra data in order to correctly render. Seeing as i only really have one file in my pages folder, i only have access to one getStaticProps call. Fetching all possible data for all possible routes seems quite wasteful.
Server side data fetching at the component level would solve his issue but this doesn't seem to be a supported feature in nextjs
Is there a recommended way around this? Conditional data fetching based on context inside getStaticProps ? 🤔

Where you should fetch data depends on the nature of your data. Also, when a user needs the data. You can use getStaticProps, getServerSideProps or fetch data on the client-side. See documentation to learn differences between the methods.

Related

Best way to paginate data with Firestore and Next.js for SEO

I use only firestore admin to access the database.
I have a function to retrieve the data from firestore. Given a collection name and option parameters (orderBy, startAt, endBefore, limit or limitToLast), it returns the resulting data in an array as well as a string with the url for the next page query and another one for the previous page. Something like this:
export interface FirestorePaginatedResponse {
data: any[],
nextParams?: FirestoreQueryOptions,
prevParams?: FirestoreQueryOptions,
}
export async function paginatedQuery(
collectionPath: string,
basePath: string,
options: FirestoreQueryOptions,
) {
[...]
return {
data,
nextParams,
prevParams,
}
}
So, considering that Static Page Rendering is not an option for Firestore pagination, what would be best for SEO A or B?
A. Do the pagination client side. One landing page with getStaticProps to load the initialData, and then use useSWR hook to retrieve and prefetch the data client side for the next pages. With useSWR probably we would save some reads to firestore due to caching and due to static generation the loading time of the first page would be faster.
B. Do the pagination with server side rendering. The landing page would have a getServerSideProps function to load the data directly given the query parameters before the page is rendered. I think that server rendering might be better for SEO, but maybe the loading of the page would be slower.
In any of those cases the query parameters are read from the url, and the pages are navigated using next/link with href to do the client transition between pages.
EDIT:
I tested 2 pages for pagination with the same content one with getServerSideProps and another one with getStaticProps. The initial loading time of the page is almost the same, so I think I'll be going with the server side rendering as xBurnsed said, for SEO it's better ssr than csr.
As far as I am concerned, the best approach for pagination when it comes to Firestore is to start at the first page, and then cycle through the results using startAfter() with the info of the doc where the last page ended. You can find more information in the following documentation.
Since pagination is meant to prevent loading all documents, I would choose to fetch the documents for each page on demand using the above described method.
Server-side rendering is considered a better option for SEO than client-side rendering. This is because server-side rendering can speed up page load times, which not only improves the user experience, but can help your site rank better in Google search results.
Server-side rendering is also better for SEO because it removes the burden of rendering JavaScript off of search engine bots, which makes it faster for them. Also, not all search engine bots are able to run JavaScript, as stated here.

How to put RTK query into store/slice?

I just started using RTK query, but facing a problem
My app has all the setting in one big JSON, so I create an RTK query to fetch the setting. In the tutorial, the examples are about using the useQuery hook in the component and immediately display the result, but because the setting is so big that it has multiple pages/components to display it and allow the user to change the setting
Because the setting needs to be changed, so I think it's a good idea to put the state in the store, my question is how can I put the API result into the store?
I can see a couple of methods around it
Use useQuery in a component and when it has resulted, then do a dispatch to put the data onto the store
put useQuery from API in all components use it and use it to get cached data, then there is no need to put it on the store and use the component state for setting changes (I'm not sure about this approach as there are a lots of settings - even divided across different pages, it doesn't seems right use component state to manage it)
I'm new to RTK and RTK query, just wondering what's the best/good approach?
Using RTK Query implicitly means "putting your data in the store". It creates a store slice that manages all your data for you.
You can just use useQuery wherever you need that data and you either get it out of the store or request it new when necessary.
Most of the time you should not copy that data elsewhere as you will have to do stuff like manual cleanup etc. then.
I can also recommend going through the tutorial chapters for RTK-Q that were just added to the official Redux tutorial. They are very in-depth.
https://redux.js.org/tutorials/essentials/part-7-rtk-query-basics
From the docs:
However, when you use RTK Query, there is a mindset shift that happens. We're no longer thinking about "managing state" per se. Instead, we now think about "managing cached data". Rather than trying to write reducers ourselves, we're now going to focus on defining "where is this data coming from?", "how should this update be sent?", "when should this cached data be re-fetched?", and "how should the cached data be updated?". How that data gets fetched, stored, and retrieved becomes implementation details we no longer have to worry about.

Next.js : getStaticProps with context API

I'm currently building my first next app (e-commerce with Shopify Storefront API).
In order to avoid multiple query to the db and upgrade performance, I want to store all datas once a user sees a page:
1- first loading (by page): the method getStaticProps fetch the necessary datas and put everything in a context ShopContext
2- when the user hits the page another time: instead of getStaticProps re-fetch the datas, just use the data in the context.
Is it something logical to do that? And if yes, is it possible to avoid data fetching when a loading page occurs?
Many thanks for your responses ! :)

React + SSR: Correct way to handle a component that needs to fetch data first

I currently have a React app that I'd like to use SSR with. All but one component is pretty much static content, making SSR super easy. Everything but the component is rendered just fine and well right now.
My question is how do I go about rendering this component that needs to first get data? Because it's a complex SVG that gets rendered my line of thinking is that having it "update" once data comes in is a bad move, and it would be better for it to just not exist in the absence of data (with an error message).
So here's my plan: I can add a prop to the component to pass in data from a parent rather than keep it as internal state only. So if data is passed, no fetch request in the component is necessary. From there what I can do is take the static bundle output of the app and, when the page is requested, the server will request the proper data just as the component would. Once the data is received, the server can grab the component from the bundle with regex, add the data as a prop, render the component, and stick it back in with the rest of the already rendered static content.
Is this the correct way to do this? It feels a bit complicated, but that might just be how it's done. I'm not sure.
Your intuitions are correct. In current React (17.0), it's quite cumbersome to do SSR with data-fetching inside components.
What needs to be achieved on a conceptual level is that all data dependencies need to be known upfront, ie. before calling ReactDOM's render. This way, one can access the data in a synchronous manner which allows to do one-pass render on a server.
I don't quite follow your idea to "grap the component from the bundle with regex". One way of solving the data dependency problem is to inject the data into React tree from the root component (ie. ReactDOM.renderToString(<App componentStaticData={data} />)) and make the data-dependent component aware of the fact that it can just grab the data from there instead of doing (asynchronous) call. It's important to note that useEffects are not executed on the server.
Another idea to grab all the data dependencies is to do two-pass render. First one is used as a way to collect all resources used, then we await their completion and inject them as static data into send pass.
Third way is to use one of the React frameworks that provide SSR out of the box. You can have a look at (among many others) Next.js or Gatsby. Depending on your setup, this might be easiest or the hardest way to achieve SSR.

Query with Apollo in SSR and Dynamic URLs (Next.js)

I'm developing a project that uses dynamic URLS like [slug].js what I'm trying to do is: when someone access some url like domain.com/my-post my page should query for available slugs (that contains data like SEO metatags) in a graphql endpoint and load the page if the url exists in my database.
I`m using SSR, apollo hooks and etc.
My question is: on production when someone share that url on facebook or things like that the metatags on that url (domain.com/my-post) will be the empty ones (before query looks for available slugs) or after the metatags and contents was full filled? considering that when I use useQuery from apollo I need to return something in order handle loading and error from that query. I'm some point when users access that url will show a "loading" message.
My question is: on production when someone share that url on facebook
or things like that the metatags on that url (domain.com/my-post) will
be the empty ones (before query looks for available slugs) or after
the metatags and contents was full filled?
It depends on where you make the request for the slug.
If you make the request server side (ex. inside getInitialProps) pages will wait to fetch data before pre-rendering, that means that when the page will render, it will render with metatags.
If you are following the with-apollo example it should render server side obviously only if you are using your HOC in pages else if you are importing your HOC deeper in your component Tree, getInitialProps will be ignored (since it work only in pages)

Resources