Access the url that user has entered from in getServerSideProps Next JS - javascript

I am currently trying to find the page that the user has came from to enter this current one in the server side props, im not sure if thats possible? or are there any ways that i could access that
TLDR: get the url which user is coming from and not where is going to, example:
coming from: http://localhost:6060/product/id/55555-62/
going to: http://localhost:6060/products/
I would like to access the id query, in the /products/ getServerSideProps
export const getServerSideProps = wrapper.getServerSideProps(store => async ({ req }) => {
console.log(req);
return {
props: {},
};
});

https://nextjs.org/docs/api-reference/data-fetching/get-server-side-props#context-parameter
resolvedUrl: A normalized version of the request URL that strips the _next/data prefix for client transitions and includes original query values.
export const getServerSideProps = (ctx) => {...}
Inside ctx you can find params, query, resolvedUrl etc

Would the referrer enough for the thing you needed it for?
req.headers.referer
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer

Related

fetch data by useEffect in a server side rendering page

I have a project with react js and next js. I am developing a dynamic page, with getStaticPaths and getStaticProps. So I am fetching most of the data in getStaticProps to make the page be rendered on server side.
But there are some data which I can't fetch on server side, because it needs token which is stored in local storage.
The question is, if I use useEffect hook to fetch those data on client side, does this all process make any advantage for SEO?
Or I have to change structures, and store token in cookies to fetch all data on server side?
Update:
I want to check if user is logged in, and based on the result, show the page in different styles. But no user-related data is going to be rendered.
Right now, my code looks like this:
export default function BookDetail(props) {
const [isLoggedIn, setIsLoggedIn] = React.useState(false);
React.useEffect(() => {
// It captures token from cookies
const token = getCookie("token");
// Then I need to confirm that token is valid from backend
if (token) {
setIsLoggedIn(true);
}
}, []);
return (
<div>
{ !isLoggedIn ? (
{props.res.data.title}
<br/>
{props.res.data.description}
) : (
{props.res.data.title}
<br/>
<button type="button" onclick={()=>{window.location.href='http://example.com';}}
)}
</div>
);
}
If you need a token to fetch said data, that data is probably related to the user? Hence, doesn't and shouldnt be considered with SEO.
If your data is not specifically for the user. Consider making it accessable without token.
Edit based on the comments here:
Fetching data inside useEffect will absolutely affect SEO. You want to display part of a book (text) for users that are not logged in. You check if users are logged in by a request from the useEffect, this is fine and standard.
If you want to Google to be able to read your book-text with crawlers you can not fetch it in useEffect, I suggest the following:
in your getStaticProps: Fetch the data (book text) and pass it to your page. Display this information by default.
Then in your useEffect you check if the user is logged in. If they are --> remove the text and render a button instead.
This way, Google will read it as you intend, while logged in users will only see a button.
You can check no problem on the server side whether a user is logged in only when you use getServerSideProps - getStaticProps are executed at a built time so there is no communication with whatever user inputs into the UI simply because thats a different time frame: building the app on the server, only when the app is built user can interact with it.
But getServerSideProps are not executed at a built time, yet there are still executed on the server side and since useEffect is a frontend API it won't work there. So there are two ways:
If you use NextAuth - you can use getServerSideProps and on the context object you have 'req' property and the property passed to the getSession function (you need to import that function) will tell you whether user has a session or not. Here is an example code snipet:
import { getSession } from "next-auth/react";
// some code here like your frontend component
export const getServerSideProps = async (context) => {
const { req, res } = context;
const session = await getSession({ req: req });
if (!session) {
return {
redirect: { destination: "/", permanent: false },
};
}
const email = session.user.email;
return {
props: { email: email, session },
};
};
Here is more on the subject from the official next docs:
https://nextjs.org/docs/authentication
If you don't use NextAuth I am sure you can attach your token to the context object like in the example above and read it in getServerSideProps except not use getSession as that is NextAuth API. haven't done it though.

How to create an express update route with multiple parameters

I want to update an attribute within a JSON object using fetch PUT. I've created a put function taking in 2 URL parameters
app.put('/trustRoutes/:id/:item', (req, res){
I am able to update the data with a single parameter but since I only want to change one value inside that object, calling put will replace the whole object with my new body.
below is what I've tried.
app.put('/trustRoutes/:id/:item', (req, res) => {
readFile(data => {
const userId = req.params['id/item'];
// have also tried const userId = req.params.id.item
data[userId] = req.body;
//write data back to file
I looked around at other examples but couldn't find any that were updating data instead of GET. If there is one I missed please let me know.
PUT requests are great for completely overwriting a resource, and is idempotent. This answer does a good job explaining idempotency. For updating a resource partially, a PATCH request is a better choice.
app.patch('/trustRoutes/:id/:item', (req, res) => {
readFile(data => {
data[userId] = req.params[id];
data[item] = req.params[item];
// A get request for this resource would now show both of the updated values
// Write file

What's the proper way to use RTK Query when dealing with multiple base URLS?

I have migrated towards RTK and enjoying it immensely so far, but one thing I got stuck on is the following situation:
We have (for keeping it simple's sake) two endpoints:
www.domain-customer.com <- fetching customer data
www.domain-order.com <- can mutate some user data here
And the website itself is hosted on another domain.
I need to fetch data from the customer endpoint, but in order to update certain things I need to make a mutation to the order endpoint. At first I thought I should define a createApi per base URL, but then I'm pretty sure I can't have the invalidation. I would like to have this previous mutation invalidate the data for the customer, so that the new data gets refetched.
So this is what I have come up with, but I'd like some input on if this is the way to move forward.
export const customerApi = createApi({
reducerPath: "/../",
baseQuery: fetchBaseQuery({ baseUrl: "https://www.domain-customer.com/" }),
endpoints: (builder) => ({
// write provides tag stuff here
getCustomerExample: builder.query({ query: (name) => `customer/${name}` }),
// please ignore the details of the mutation, I haven't practiced much with it yet.
updateCustomer: builder.mutation({
queryFn: async (name) => {
const response = await fetch(
`https://www.domain-order.com/updateCustomer`,
{update mutation stuff here}
);
const data = await response.json();
return { data };
}
// write invalidate stuff here
})
})
});
Is this the way to go about it? Or should there even be a giant createAPI that will hold all the mutations and queries?
Generally, yes, you should have one single createApi if data is connected enough that you want to invalidate them.
Note that while most examples just show queries to something under baseQuery, you can also just have a url parameter (or string) returned from query that contains a full domain -fetchBaseQuery 100% supports that use case.
So in your case:
updateCustomer: builder.mutation({
query: (name) => ({
url: `https://www.domain-order.com/updateCustomer`,
// update mutation stuff here
})
// write invalidate stuff here
})

Use Next.js Dynamic routing query object in an SWR fetch request

When using Next.js dynamic routing I'm trying to make an SWR fetch request using the routing query object, but my SWR fetch request is being called before the query object is set.
Given the dynamic route /posts/[id], consider the page /posts/123.
import { useRouter } from 'next/router';
import useSWR from 'swr';
export default function MyPage() {
const router = useRouter();
const { id } = router.query;
const url = `https://my.api.com/posts/${id}` // I've also tried using let here
const { data, error } = useSWR(url, fetcher);
console.log(url)
This URL initially console logs as https://my.api.com/posts/undefined and an error is returned from the API because https://my.api.com/posts/undefined is, of course, not a valid path.
Immediately after, the URL console logs correctly as https://my.api.com/posts/123 and the data on the page usually then populates, but sometimes the data doesn't populate and it's stuck in a 'loading' state. When I hardcode the URL this never happens.
Is there something I'm doing wrong here? Why is the query object not available immediately? Is there a way to elegantly wait for it to be set?
You could try to use conditional data fetching like so:
const { data, error } = useSWR(id ? url : null, id ? fetcher : null);
Also check following conversation: https://github.com/vercel/next.js/discussions/15952

Can't get url Parameter inside controllerFunction node js

In my index.js I have given routing in such a manner.
app.use('/users/:id/transactions',transactionRoutes)
Inside transactionRoutes
router.get('/:txnHash',transactionController.getTransaction);
so request to '/users/:id/transactions/:txnHash' will come to the above route.
Inside transactionController
module.exports.getTransaction = (req,res) => {
let typeOfTransaction = req.query.type,
userId = req.params.id,
txnHash = req.params.txnHash;
}
Here I am able to access the txnHash parameter but the userId parameter shows undefined. I think it is because the :id part of the route is specified in the index.js. Is there any method to solve this problem without changing the routes.
API Request is
GET 'apiurl/users/42342234/transactions/234bh2428b354hjcs'
In your TransactionRoutes you need to add mergeParams which will preserve the req.params values.
var router = express.Router({mergeParams: true});
Before your,
router.get('/:txnHash',transactionController.getTransaction);
Hope this helps!

Categories

Resources