NextJS posting a form to internal API - javascript

In the Next.JS documentation I read the following.
Note: You should not use fetch() to call an API route in getStaticProps. Instead, directly import the logic used inside your API route. You may need to slightly refactor your code for this approach.
Fetching from an external API is fine!
But if I'm not supposed to use the internal API then two questions arise.
How can I handle POSTS? Should I handle POSTS / PUTS etc through the API but not GETS? That seems odd to me.
If I also should not do 'internal POSTS etc' why is the API option there?
edit:
Hmm. I suppose one of the reasons is that when using getStaticProps, and compiling a static version of the site, # compile time the API is potentially not running. But that could be easily solved by running the API at the same time. (Since GetStaticProps is not really relevant for interactive pages, so POST etc)
edit2:
Someone here also figure that out. Next.js - Error: only absolute urls are supported run export and sever separately and then you can do fetch in static props when needed. Then at least all stuff is in one place.

The function getStaticProps is meant to generate the data on the server-side when the page is loaded.
Answer 1: You should handle POST/PUT/GET, etc in your API routes.
Answer 2: The main difference between getStaticProps and API is the time they are run. getStaticProps is run when the page is generated on the server. API can be called anytime you need them.

Related

Configuration Files in Next.js

So, I have a functional application that is working fine, I', using Next.js and Next.js api tool to do all the requests. I'm using sanity.io for my backend. Thats all ok.
For my sanity config, I have a configuration file called 'sanity.js', that's have all the sensitive content.
What is the deal, if the user go into source in the develop console, he founds all the sensitive data. I know if I put this "const config" and "const editor" inside the API, this data will be hidden, but I need to use this 'const config' in more than 1 file, and I don't want to repeat code.
1st doubt: Is there some way to do this process without repeating code, like creating a configuration file inside API, and reuse the const's inside it.
2st doubt: The const 'urlFor' is used in the frontend to manage the images, how to deal with this if the configuration file must be only in the API, and the 'urlFor' needs this configuration in parameter to run properly.
projectId, dataset and apiVersion are not considered sensitive data and they will be visible in all of your queries, so they can be safely exposed to the browser. The token however, is sensitive indeed. Don't expose the token to the browser with NEXT_PUBLIC prefix as the value will be inlined into JavaScript sent to the client.

Data fetching in next js

There are many ways to fetch data from apis in next.js.
getServerSideProps,getStaticPaths,getStaticProps,Incremental Static
Regeneration and client side rendering.
If I have to make requests to backend on the change of any state, can I use other methods of data fetching apart from client side rendering?
I am from React.js background where client side rendering is mostly used.
What are the specific use cases of different fetching methods?
Can I always use client side rendering only in Next.js also.
Server-side rendering is good for SEO. You can check this, if you view the page source of a react app you won't get much HTML, this is the problem next.js fixes. With getServerSideProps and getStaticProps you can make calls to your API(such as DB back-end) to get your data and server-side render your page. Now when you have to update state of your page you can simply fetch as you normally would, since it doesn't matter because it is triggered by some action anyway.
Can I always use client side rendering only in next.js also.
Yes you can, but you want search engines to index your site and/or display relevant data such as review and preview text, right?
If I have to make requests to backend on the change of any state, Can I use other methods of data fetching apart from client side rendering
When the state is changed you will fetch new information just like you normally did in react.
GetServerSideProps and GetStaticProps only run once when the user visits the page(or reloads etc ofc). You can get the latest data by fetching and updating state with that.
Next.js is much more than react, it can be used as a back-end too i.e. creating APIs for saving data to db, handle authentication etc. Explaining it all is beyond the scope of this answer.
As for when to use what you can read more about it here, or search about it I'm sure SO has many questions about this.
One situation where you can be forced to use next.js features is when you want to consume an old API that does not implement CORS, here you can't control the dev on the other side so you can create an API on next.js which you fetch on your react code like: /getinfo. Now write code on your back-end to handle this which will delegate the result of that third-party API back to you, pretty neat right

Dumb question: Concern regarding using backend server's REST API in React app

Like in order to connect(basically making request's) our React app to our backend server we have to use backend REST API, like logging in user, fetching data from the backend.
But wouldn't using REST API on the React components make API available to every user and any malicious mind could create chaos or make unnecessary requests to the server(like using Postman).
Is there any way to hide API keys, I've seen another answer to a similar question on 'How to hide API Keys' but there's not a clear answer, some saying to prepend API with REACT_APP_ in a dotenv file but some saying this is not safe, although I've tried prepending REACT_APP_ but still API is visible on the front end.
Is there a solution available to this problem?
Using a REST API from your react app does not expose those endpoints to the public. By virtue of that REST API existing, those endpoints are already exposed to the public and anyone in the public can use them. It's the servers job to make sure those endpoints are locked down and secure (requires authentication, etc), not the clients.

How to fetch data only once in a Next.js app and make it accesible to all the app, both in server and client

I'm working on a Next.js app that needs to fetch a config file from a remote server before initializing. I want to request the config file just once per call to the server before rendering the app server side. After that, I would like to be able to get the same config in the client without having to make a second request to the remote server from the browser.
I have tried to achieve this by using getInitialProps function either in _app or _document files and then use the React's Context API to make the configuration visible to every component but unless I'm wrong, this will run the code that requests the configuration both in server (on the first call from the browser) and client (on every page navigation).
I have also tried to create a server.js file, request the configuration from there and store in a variable within a ES6 module. However, I couldn't make this approach work because apparently the Next.js React app can't access the same modules than the server.js because they are actually two different apps. Again, I could be wrong.
Basically I would like to know if Next.js offers any kind of "bootstrapping place" where I can perform app initialization tasks that generate data that can be sent to the React app Next.js will initiate.
You are correct in that anything in getInitialProps in _app.js or _document.js will be run on every server request. Once you get your config, you can pass it down to the components in pages as props. From there, I think you have two choices:
Now that the app is bootstrapped, run the rest of the app as a SPA client-side. This would prevent any future SSR from happening. Obviously, you lose the benefits of SSR and the initial page load is likely longer, but then it would be snappy afterwards.
After getting the config in _app.js, send it as a cookie (assuming it's not too big to be a cookie?). On future requests to the server, the cookie will be sent automatically and you would check the cookie first - if it doesn't exist, get the config. If it does exist, skip that more expensive bootstrapping because the app is bootstrapped.
So I think it really depends on whether you want a single page application bootstrapped on the server but then entirely client side after that (option 1) or server side rendering per page while minimizing expensive bootstrapping (option 2).
Nothing prevents you from sending multiple cookies from the server if that makes sense for your app and bootstrapping. And remember not to make it a HTTP-Only cookie because you'll want to read that cookie client side - after all, that's what you're looking for - the client side configuration generated on the server.
Despite we ended up leaving Next.js for this and other reasons that made us decide Next.js was not the best option for our use case, we kind of mitigated this problem as follows while be sticked to it, I hope it makes sense to anyone. Also, by now maybe Next.js provides a better way to do this so I would read the Next.js docs before using my approach. Final note: I don't have access to the code anymore since I change to a different company so maybe there are some points that won't be 100% as we made it.
There is goes:
We created a module that was responsible to request the config file and keep the results in a variable. At the moment of importing this module, we ensure that the variable is not already present in window.__NEXT_DATA__. If it is, we recover it, if it's not, we request it to the remote server (this will be helpful in the clint side rendering).
We created a server.js file as described by Next.js docs. In this file we make the call to get the config file and store it in memory.
In the body of the function passed to createServer we add the config file into the req object to make it accesible to the app in the getInitialProps functions server side.
We made sure that the getInitialProps using the config file returns it, so that it will be passed to the components as props and also serialized by Next.js and made available to the client in the __NEXT_DATA__ global Javascript variable.
Given that the config ended up in the __NEXT_DATA__ variable in the server, using the trick described in the step 1 makes the app not request the config for a second time.

node.js and single page web application

I am looking at express.js for the back end and JS on the client side.
My app is a single page Web App.
The server will only serve JSON messages and my question is about "routing" for express.
Is one supposed to use routing to connect the UI and the server side business logic?
How will that work with my single page app?
so lets say, the client makes an Ajax call to the server looking for a value in the database and there is server side script that provides the JSON back to the UI. How is this UI and node script relationship setup?
Can someone shed some light on this?
Single page apps are those that live on a single HTML document. This means that if you want to display some different content to the user, depending on the state of the application, you will need to do some DOM manipulation (cutting out and replacing certain elements of the current document with different HTML) in order to update the 'view' that the user sees. Excuse me if this is obvious to you, please don't take offense. I figured I'd start from here. Hang with me and I'll explain how your routing situation is going to play out (more or less).
URLs are composed of a few different parts, each of which informs the browser of a particular bit of information that is required in order to download the resource that the user is attempting to access. Typically the resources that you are looking for are off on a server somewhere and the browser knows this because of pieces in the URL like 'protocol' ('http:') and 'host' ('www.mydomain.com'), so it goes off to that server to find what you're requesting. There are also 'query' parameters in URLs which provide some additional information to the server regarding a particular action, like the search terms of a search query. After the query parameters, comes the 'hash'. The hash is where the magic of single page apps happens... eh, well, kind of.....
First a bit about the hash. When you add a '#' to a URL, the browser then interprets the information that comes after it to be some location (element) within the currently displayed document. That means, if you have an element with an 'id' of 'main' and you add '#main' to the end of the URL, like so: 'http: //www.example.com#main', the browser will 'scroll' (typically 'jump') to the beginning of that element, so that the you can see it. Be aware, though, that if you type 'http://www.example.com/#main' (with the hash separated from the URL by a slash) then you will force a complete page reload and the browser will attempt to find a file by the name '#main' on the server (I bet it doesn't find it).
The takeaway here is that the browser will not attempt to navigate away from the current document if there is a hash in the URL, the exception being of course the case mention above, and this is great because single-page apps don't want to navigate away from the page or request a new document from the server. (See how routing is different for single-page apps?)
Now, this whole thing about the hash isn't vital to single-page apps, as you could make one without dealing with it all. A bunch of click handlers and DOM manipulation is all you'd need really... But, that would mean that users will have no way of sharing links to particular views in your app. The URL would never change, and we would never be able to navigate to any particular view directly. We'd always be starting from the starting position of your app, which could easily be a very annoying situation.
If your single-page app is going to have different views, and you want users to be able to navigate directly to particular ones via bookmarks or links, then you will need to implement a form of routing on the front-end in addition to the routing that you'll need to implement on the backend (routing for data API, etc.), which means that you will need to make use of the hash.
I don't want to get into how different frameworks accomplish routing on the front-end, but it's basically a matter of updating the browser's address field when the user clicks a link, and watching the address bar to determine what the current URL is and loading the HTML that is associated with that URL into the DOM in the designated location in the document tree.
So, within a single-page app, you have one route on the server that deals with rendering the app HTML document (index.html), and you have routes that are responsible for dealing with the data of your app (creating new instances in the database, logging in and out, editing or destroying instances in the DB, and fetching data...) which are called via AJAX requests.
This is actually a fairly complicated situation in that HTML5 allows us to be able to forgo the hash (with the help of some link rewriting on the server) and also be able to use the 'back' and 'forward' buttons as if we've actually navigated away from the original document (which we haven't because we have only pointed the browser to the exact same URL, only with modified hash values, so no new page loads have occurred). Traditional site navigation and linking can be achieved by utilizing the browser's History API, which is available for IE beginning with version 10 (I believe), the rest of the big browser vendors were already on to it quite a bit earlier, so frameworks that leverage this technology will allow your users to navigate your app without the hash in the URL. Explaining this is a diversion and not necessary for understanding routing in single-page apps, but it is interesting and you'll have to learn it eventually anyway, probably..
AJAX should be used to request JSON from the server. AJAX requests will always hit your server because you don't include the hash symbol in AJAX requests (it would be ridiculous to do so because the hash is meant only for in-document browsing), so server-side routes must be responsible for exposing your data API (consider a RESTful one). While this is not their sole purpose in single-page apps, it is perhaps their most important one.
Soooo, to wrap it up, you will have two sets of routes. One on the client (as part of a client-side framework like AngularJS or EmberJS, the list goes on... I prefer Angular, but there is a fairly steep learning curve for that one.), and one on the server. When you think about 'server routes' think data API. When you think of 'page routing', remember that this all gets handled on the client, by the javascript that you delivered with the initial server response (this is the one and only necessary server-side route involved with rendering HTML to the browser, loading your 'index.html' and all of the necessary scripts and stylesheets, etc). You will use express.static middleware to serve static files, so you don't have to worry about assigning routes for that stuff.
EDIT A quick mention of AJAX implementation.
On the server, you will have routes similar those that Alex has provided as examples and you will make calls to those URLs from the client using whatever XMLHttpRequest (XHR) object is exposed by your framework or library of choice. It is now considered more or less standard and best practice for frameworks/libraries to implement these requests as Promises http://wiki.commonjs.org/wiki/Promises/A. You should read a bit about it on your own, but I might be able to summarize it by saying that it is an asynchronous operation analogous to 'try, catch, throw' in synchronous operations. You will instantiate a promise object and through it you will attempt to load data from the server, for instance, via GET request. Make sure that you have assigned functions to handle requests made to the URL that you made the request to (server-side route)! This object that you instantiate and subsequently make the request to the server through, promises to return the result of the request to you once it comes back from the server (no matter whether it was successful or not) If it is successful, it will call a function that you have written and will supply it with the data from the server. If it fails, it will call a different function, also written by you, and will supply it with the error object (or 'reason' for failure), so you can handle the error appropriately.
Hope that helped answer your question.
You only have to route requests you serve dynamically. Your HTML, CSS, JS are all static assets. So all you need to handling routing for is your data.
It sounds like you want a Restful API, which basically means that you have URLs for specific resources, and HTTP verbs for manipulating them.
Something like:
GET /books.json - Get all books
POST /books.json - Create a new book with properties passed in the body of the request
GET /books/123.json - Get book with id of 123
PUT /books/123.json - Update an existing book with properties passed in the body of the request
This blog post seems to show how to set this up in Express.
Once you have a sane API delivering JSON, you just make your AJAX calls use it based on what objects you want to fetch.

Categories