Next.js Discord

Discord Forum

params.slug is not defined

Unanswered
Lutherr ∴ posted this in #help-forum
Open in Discord
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 ?
'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 ∴
@B33fb0n3 Can you provide the specific structure of your pages? <@201285952318996480>
did you talk about that ?
\app(boutique)\vehicules[slug]\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
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 !
@Ray that mean item.slug is undefined
but the DOM got url generated on link
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} />
}
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
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...
the second one
you can't use useContext in server component
btw, I would use zustand or signal
zustand is insane !
never saw this module before
thanks !
thanks for all !