params.slug is not defined
Unanswered
Lutherr ∴ posted this in #help-forum
Hi everyone,
I made a simply code with the new experimental Apollo module to fetch graphql data from a wordpress CMS.
But when i entre or exit a page params.slug is undefined. But the part of this is when i reload the page params.slug is defined and appolo return an error because he cannot fetch data (apollo needs slug data). Can someone explain what happen ?
Should i change all structure to use server Component ? or i continue to use Client component.
Thanks
I made a simply code with the new experimental Apollo module to fetch graphql data from a wordpress CMS.
But when i entre or exit a page params.slug is undefined. But the part of this is when i reload the page params.slug is defined and appolo return an error because he cannot fetch data (apollo needs slug data). Can someone explain what happen ?
'use client'
import Image from 'next/image'
import AddToCartButton from '@/app/components/boutique/addToCartButton'
import Link from 'next/link'
import {getProduct} from '@/lib/queries/get-product'
import { useSuspenseQuery } from '@apollo/experimental-nextjs-app-support/ssr'
import { Suspense } from 'react'
export default function Vehicule({params}){
console.log(params) <------ IS UNDEFINED
const {error, data} = useSuspenseQuery(getProduct,{
variables : {slug: params.slug}
})
if (error) console.log(error);
return (
<main>
<div className="container mx-auto">
<Link href={`/vehicules`} >Retour </Link>
<Suspense fallback={<p>Chargement ...</p>}>
<h1 className="text-3xl font-bold underline">{data?.product.title}</h1>
<Image
src={data?.product?.featuredImage?.node?.sourceUrl}
alt="Picture of the author"
width={500}
height={500}
/>
<h2>{data?.product.price}</h2>
<h3>{data?.product.stockStatus}</h3>
<AddToCartButton data={{product_id : data?.product.productId}} />
</Suspense>
</div>
</main>
)
} Should i change all structure to use server Component ? or i continue to use Client component.
Thanks
40 Replies
Can you provide the specific structure of your pages? @Lutherr ∴
\app(boutique)\vehicules[slug]\page.js
app(boutique)\vehicules\page.js
'use client'
import Image from 'next/image'
import AddToCartButton from '@/app/components/boutique/addToCartButton'
import Link from 'next/link'
import {getProduct} from '@/lib/queries/get-product'
import { useSuspenseQuery } from '@apollo/experimental-nextjs-app-support/ssr'
import { Suspense } from 'react'
export default function Vehicule({params}){
console.log(params) <------ IS UNDEFINED
const {error, data} = useSuspenseQuery(getProduct,{
variables : {slug: params.slug}
})
if (error) console.log(error);
return (
<main>
<div className="container mx-auto">
<Link href={`/vehicules`} >Retour </Link>
<Suspense fallback={<p>Chargement ...</p>}>
<h1 className="text-3xl font-bold underline">{data?.product.title}</h1>
<Image
src={data?.product?.featuredImage?.node?.sourceUrl}
alt="Picture of the author"
width={500}
height={500}
/>
<h2>{data?.product.price}</h2>
<h3>{data?.product.stockStatus}</h3>
<AddToCartButton data={{product_id : data?.product.productId}} />
</Suspense>
</div>
</main>
)
} app(boutique)\vehicules\page.js
'use client'
import Link from 'next/link';
import { getVehicules } from '@/lib/queries/get-products';
import { useSuspenseQuery } from '@apollo/experimental-nextjs-app-support/ssr';
import { Suspense } from 'react';
export default function Vehicules(){
const {error, data} = useSuspenseQuery(getVehicules)
if (error) error;
return(
<main>
<h1>Véhicules</h1>
<Suspense fallback={<p>Chargement</p>}>
<ul>
{
data.productCategory.products.nodes.map((item, i) => {
return (
<li key={i}>
<Link href={`vehicules/${item.slug}`}>{item.name}</Link>
</li>
)
})
}
</ul>
</Suspense>
</main>
)
}lib\apollo.js
'use client'
import { ApolloLink, HttpLink, } from "@apollo/client";
import { relayStylePagination } from '@apollo/client/utilities';
import {
NextSSRApolloClient,
ApolloNextAppProvider,
NextSSRInMemoryCache,
SSRMultipartLink,
} from "@apollo/experimental-nextjs-app-support/ssr";
/**
* Middleware operation
* If we have a session token in localStorage, add it to the GraphQL request as a Session header.
*/
export const middleware = new ApolloLink( ( operation, forward ) => {
/**
* If session data exist in local storage, set value as session header.
*/
const session = ( typeof window !== 'undefined' ) ? localStorage.getItem( "woo-session" ) : null;
if ( session ) {
operation.setContext( ( { headers = {} } ) => ( {
headers: {
"woocommerce-session": `Session ${ session }`
}
} ) );
}
return forward( operation );
} );
/**
* Afterware operation.
*
* This catches the incoming session token and stores it in localStorage, for future GraphQL requests.
*/
export const afterware = new ApolloLink( ( operation, forward ) => {
return forward( operation ).map( response => {
if ( !typeof window !== 'undefined' ) {
return response;
}
/**
* Check for session header and update session in local storage accordingly.
*/
const context = operation.getContext();
const { response: { headers } } = context;
const session = headers.get( "woocommerce-session" );
if ( session ) {
// Remove session data if session destroyed.
if ( "false" === session ) {
localStorage.removeItem( "woo-session" );
// Update session new data if changed.
} else if ( localStorage.getItem( "woo-session" ) !== session ) {
localStorage.setItem( "woo-session", headers.get( "woocommerce-session" ) );
}
}
return response;
} );
} );
const typePolicies = {
RootQuery: {
queryType: true,
fields: {
products: relayStylePagination(['where']),
},
},
};
const client = function createClient(){
const httpLink = new HttpLink({
uri:`${process.env.GRAPHQL_ENDPOINT}`,
fetch: fetch
});
return new NextSSRApolloClient({
cache: new NextSSRInMemoryCache(),
link:
typeof window === "undefined"
? ApolloLinnk.from([
new SSRMultipartLink({
stripDefer: true,
}),
middleware.concat( afterware.concat(httpLink)),
])
: middleware.concat( afterware.concat(httpLink)),
});
/*return new ApolloClient({
link: middleware.concat( afterware.concat( createHttpLink({
uri: `${process.env.GRAPHQL_ENDPOINT}/graphql`,
fetch: fetch
}) ) ),
cache: new InMemoryCache({typePolicies}),
});*/
}
// Apollo GraphQL client.
export default function ApolloWrapper({ children }) {
return (
<ApolloNextAppProvider makeClient={client}>
{children}
</ApolloNextAppProvider>
);
}<Link href={
/vehicules/${item.slug}}>{item.name}</Link>try add a slash?
@Ray try add a slash?
same error 😦
1: Click on link
2: Redirect to not-found
2: Redirect to not-found
There is the link in my url bar
what happends, when you add a slash like:
/vehicules/${item.slug}/
i need to reload my page to show the page
how about you type the url?
localhost:3000/vehicules/123
@Ray how about you type the url?
oh works fine
that mean item.slug is undefined
that's why i use typescript lol
@Ray that's why i use typescript lol
lol i think i will start typescript !
could be problem with suspense query
not sure, I cant make suspense query work with SSR
@Ray not sure, I cant make suspense query work with SSR
that's what i think too but with client and server component, i don't know how to do ....
other thing, do you know how to pass data get in server component to a context ?
you mean pass data to client component from server component?
pass data from server component (getVehicules) to a client component by context (useContext to set state)
"use client";
import { createContext } from "react";
const Context = createContext({});
export function Client({ data }) {
return <Context.Provider value={data}>...</Context.Provider>;
}export default async function Server() {
const data = await getData()
return <Client data={data} />
}@Ray ts
export default async function Server() {
const data = await getData()
return <Client data={data} />
}
Thanks so context provider cannot be use in top of app ?
you can wrap the layout with the provider
export default function Provider({children}) {
return <Context.Provider>{children}</Context.Provider>;export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>
<Provider>
{children}
</Provider>
</body>
</html>
);
}ok thanks, and from this situation for example, can i do this to set information into this context
like
or
like
export default function Cart(){
const {data} await getCart();
const {cart, setCart} = useContext(cartContext) <-----
setCart(data)
return (<>
<CartList />
</>)
}or
export default function Cart(){
const {data} await getCart();
return (<>
<CartList data={data} />
</>)
}just ask because the second way is mor simple but why use context in this situation...