redirect() keeps redirecting indefinitely
Answered
PepeW posted this in #help-forum
PepeWOP
I have a product page that looks like the following:
I have two problems with this
1. I get redirected to the good url (http://localhost:3002/example?color=red&size=34) but then it keeps redirecting again and again on the same url
2. It seems like the redirect happens client side because I first see the url without the params (http://localhost:3002/example) and then get redirected to the full url
export default async function ProductPage({ params }: { params: { productSlug: string } }) {
const product = await graphqlServerRequest({
document: productBySlugQuery,
variables: { productSlug: params.productSlug },
})
...
// urlParams = "color=red&size=34"
redirect(`${params.productSlug}?${urlParams}`)
return (
...
)
}I have two problems with this
redirect():1. I get redirected to the good url (http://localhost:3002/example?color=red&size=34) but then it keeps redirecting again and again on the same url
2. It seems like the redirect happens client side because I first see the url without the params (http://localhost:3002/example) and then get redirected to the full url
Answered by B33fb0n3
then you can do it like that:
export default async function ProductPage({ params }: { params: { productSlug: string } }) {
const product = await ...
...
// calculate the url params based on default variant
return (
<CartComponent />
<SetClientsideURL params={urlParams}/>
<ProductDesc desc={product.desc} />
<ProductPic images={product.images}/>
)
}66 Replies
that's because how you handle the redirect
you fetch stuff and after you fetched it, you redirect. So you see what you saw in your second point: first without then with
so you just need to make the redirect only when a condition is true and then you broke the loop 🙂
PepeWOP
Ok i'll try to find a condition to stop the infinite redirect.
About the second point, I don't get how I'm supposed to fix that. Because I need the product to calculate the urlParams
About the second point, I don't get how I'm supposed to fix that. Because I need the product to calculate the urlParams
are you able to calc (or only pass) these params to a client component?
PepeWOP
yes I can do that why ?
then you can do the following:
your productpage only fetch the product.
the client get's the params and set them as url params (so you don't need to redirect)
because there is no redirect, there will be no loop 🙂
your productpage only fetch the product.
the client get's the params and set them as url params (so you don't need to redirect)
because there is no redirect, there will be no loop 🙂
PepeWOP
Ok I see
But ideally I would like not see any redirect.
If I request the page http://localhost:3002/example I instantly arrive on the page http://localhost:3002/example?color=red&size=34
But ideally I would like not see any redirect.
If I request the page http://localhost:3002/example I instantly arrive on the page http://localhost:3002/example?color=red&size=34
yes, there will be NO redirect, but the url will be the "changed"
PepeWOP
But because it happens client side, the user will first arrive on the page http://localhost:3002/example then the client component will render and trigger the function to set the urlParams and finally the url will change to http://localhost:3002/example?color=red&size=34 right ?
So the user will see the page "flicker"
page flicker? No, because the user won't be redirected. The url just changes. So the page stays the same and will be rendered only once
PepeWOP
When the url is http://localhost:3002/example the page is empty because it needs a default variant.
When the url is http://localhost:3002/example?color=red&size=34 the product can be seen on the page
So if the url change from http://localhost:3002/example to http://localhost:3002/example?color=red&size=34 the user will see a flicker isn't it ? Because the content changes
When the url is http://localhost:3002/example?color=red&size=34 the product can be seen on the page
So if the url change from http://localhost:3002/example to http://localhost:3002/example?color=red&size=34 the user will see a flicker isn't it ? Because the content changes
oh ok, yea, lets fix that. The params will be calculated serverside, right?
PepeWOP
Yes
On the page itself
When the user visits http://localhost:3002/example the product will be fetched and the params will be calculated, right?
PepeWOP
Yep
ok and your components on your page receives the fetched page data, right?
PepeWOP
Here's the full code:
export default async function ProductPage({ params }: { params: { productSlug: string } }) {
const product= await graphqlServerRequest({
document: privateSaleProductBySlugQuery,
variables: { productSlug: params.productSlug },
onError() {
notFound()
},
})
// find the default variant
const defaultVariantCode = product.defaultVariantCode
const defaultVariant = product.variants?.filter((variant) => variant?.code === defaultVariantCode)[0]
const defaultVariantFallback = defaultVariant ?? product.variants[0]
// find the options of the default variant
const optionsOfDefaultVariant = defaultVariantFallback.optionValues?.map((option) => [
option.option.split("/").slice(-1)[0].toLowerCase(),
option.value.toLowerCase(),
])
// add the options to the url
const urlParams = optionsOfDefaultVariant
?.map((option, index) => `${option[0]}=${option[1]}${index === optionsOfDefaultVariant.length - 1 ? "" : "&"}`)
.join("")
redirect(`${params.productSlug}?${urlParams}`)then you can do it like that:
You page will be loaded with your productdata and your product itself and the url will be set by the client. Because the Product Components already loaded and there is no reload (because no redirect), there won't be a flicker
export default async function ProductPage({ params }: { params: { productSlug: string } }) {
const product = await ...
...
// urlParams = "color=red&size=34"
return (
<CartComponent />
<SetClientsideURL params={urlParams}/>
<ProductDesc desc={product.desc} />
<ProductPic images={product.images}/>
)
}You page will be loaded with your productdata and your product itself and the url will be set by the client. Because the Product Components already loaded and there is no reload (because no redirect), there won't be a flicker
Am I missing something?
PepeWOP
Yes ^^
because I can't do
All my product infos comes from a variant and a variant is a combination of options (color=red&size=34 for example)
So the idea would be the following:
1. get to the page http://localhost:3002/example?color=red&size=34
2. find the variant from the options in the url
3. being able to do
because I can't do
product.description for example.All my product infos comes from a variant and a variant is a combination of options (color=red&size=34 for example)
So the idea would be the following:
1. get to the page http://localhost:3002/example?color=red&size=34
2. find the variant from the options in the url
3. being able to do
productVariant.descriptionWhy you don't do it here:
export default async function ProductPage({ params }: { params: { productSlug: string } }) {
const product = await ...
...
// urlParams = "color=red&size=34"
// HERE ^^^^^^^ there are the params
return (
...
)
}PepeWOP
That's what I'm doing but then I need to append
urlParams the urlThat's why I'm doing a
redirect()But maybe there is another way of appending params to an url
you only need the urlParams to fetch the variant, not the product, right?
So the product can be fetched without them, right?
So the product can be fetched without them, right?
PepeWOP
In the product I already have an array with all the variants (
product.variants) so no need to fetch anything more than the productnice
and the client can enter http://localhost:3002/example OR http://localhost:3002/example?your=params
PepeWOP
A product page is always http://localhost:3002/example
and if he enter http://localhost:3002/example they should be redirect to a default variant
PepeWOP
We can't Link to the product page with the params before hand
PepeWOP
yes
And ideally the redirect should be "invisible"
PepeWOP
yes
so, product is now fetched and variants are fetched
so you have data to display (yea I know: mulitple variants, but you only want to show one... yes, we take a look at that in the next step)
PepeWOP
yes
and if the client go on http://localhost:3002/example he should be invisibly redirect to the first variant in (I guess) your variants array or which one?
PepeWOP
yes
// find the default variant
const defaultVariantCode = product.defaultVariantCode
const defaultVariant = product.variants?.filter((variant) => variant?.code === defaultVariantCode)[0]
const defaultVariantFallback = defaultVariant ?? product.variants[0]the first variant is a fallback but that's the idea
that sounds great. Good job! And then you have data (imagine just for a moment) for the default variant and can display this default variant, right?
PepeWOP
Oh you're right
I'm stupid
alright. So the only thing that needs to be done is the invisible url change, right?
PepeWOP
I can just pass the defaultVariant as a prop and then client side change the url
but the flicker will not be seen because the content will remain the same
excatly! Or even only pass the new urlParams to the client 🙂
@PepeW but the flicker will not be seen because the content will remain the same
yes. No flicker, same content, only url change
PepeWOP
Perfect
Thank you very much for you time 😄
then you can do it like that:
export default async function ProductPage({ params }: { params: { productSlug: string } }) {
const product = await ...
...
// calculate the url params based on default variant
return (
<CartComponent />
<SetClientsideURL params={urlParams}/>
<ProductDesc desc={product.desc} />
<ProductPic images={product.images}/>
)
}Answer
PepeWOP
yep
cool, please mark solution
PepeWOP
Which message ?
^^
PepeWOP
done 🙂
Good job ðŸ‘