Adewale Perfect
Adewale Perfect

Reputation: 593

Cannot read property slug of undefined

I'm working with next.js and wordpress. I have set up my api.js. And whenever I tried to access the [slug] from another component, It shows - Typerror: Cannot read property 'slug' of undefined.

Assuming, I have another page called Test, if I try to access the post from the component with next link

<Link href={`/articles/${node.slug}`}>
    <a><h5>{post.name}</h5></a>
</Link>

It shows the Typerror: Cannot read property 'slug' of undefined

My codes works fine in the same component it was created in, but whenever I try to access it from another component with the next link; it shows the error.

I hope It's well understood.

Here's my code:

api.js:

const API_URL = process.env.WP_API_URL;

async function fetchAPI(query, { variables } = {}) {
  const headers = { 'Content-Type': 'application/json' };

  const res = await fetch(API_URL, {
    method: 'POST',
    headers,
    body: JSON.stringify({ query, variables })
  });

  // error handling work
  const json = await res.json();
  if (json.errors) {
    console.log(json.errors);
    console.log('error details', query, variables);
    throw new Error('Failed to fetch API');
  }
  return json.data;
}

export async function getAllPosts(preview) {
    const data = await fetchAPI(
      `
      query AllPosts {
        posts(first: 20, where: {orderby: {field: DATE, order: DESC}}) {
          edges {
            node {
              id
              date
              title
              slug
            }
          }
        }
      }
      `
    );
  
    return data?.posts;
}

export async function getAllPostsWithSlug() {
    const data = await fetchAPI(
      `
      {
        posts(first: 10000) {
          edges {
            node {
              slug
            }
          }
        }
      }
    `);
    return data?.posts;
};

export async function getPost(slug) {
    const data = await fetchAPI(
      `
      fragment PostFields on Post {
        title
        excerpt
        slug
        date
        featuredImage {
          node {
            sourceUrl
          }
        }
      }
      query PostBySlug($id: ID!, $idType: PostIdType!) {
        post(id: $id, idType: $idType) {
          ...PostFields
          content
        }
      }
    `,
      {
        variables: {
          id: slug,
          idType: 'SLUG'
        }
      }
    );
  
    return data;
};

[slug].js:


<article>
   <h1>{postData.title}</h1>
       <div dangerouslySetInnerHTML={{ __html: postData.content }} />
</article>

export async function getStaticPaths() {
    const allPosts = await getAllPostsWithSlug();

    return {
        paths: allPosts.edges.map(({ node }) => `/articles/${node.slug}`) || [],
        fallback: true
    };
}

export async function getStaticProps({ params }) {
    const data = await getPost(params.slug);

    return {
        props: {
            postData: data.post
        }
    };
}

GraphQL query

query AllProfiles {
  businessProfiles(where: {orderby: {field: AUTHOR, order: ASC}}) {
    edges {
      node {
        date
        title
        slug
        link
        uri
   }
}

Note: I shorten the codes due to stackoverflow validations. Now, the problem is whenever I try to access the path from another component, it shows the error I mentioned above.

I am using Next link for the routing and all.

Anyway to fix it? Please, guide me.

Thank you all.

Upvotes: 0

Views: 2290

Answers (1)

Andrew Ross
Andrew Ross

Reputation: 1158

using the graphql query from above

query AllProfiles {
  businessProfiles(where: {orderby: {field: AUTHOR, order: ASC}}) {
    edges {
      node {
        date
        title
        slug
        link
        uri
      }
    }
  }
}

assuming you're targeting that query for the slug in Link and your function looks as follows

export async function getAllProfiles() {
    const data = await fetchAPI(`
query AllProfiles {
  businessProfiles(where: {orderby: {field: AUTHOR, order: ASC}}) {
    edges {
      node {
        date
        title
        slug
        link
        uri
      }
    }
  }
}
`);
  
 return data?.posts;
}

Then, you'll want to isolate slug. How? Make a standalone getProfileSlug component.

import { getAllProfiles } from '@lib/api';
import Link from 'next/link';

const resolveProfileSlugs = async ({ ...props }) => {
    const data = await getAllProfiles();
    return data !== null &&
        data.posts !== null &&
        data.posts.edges !== null &&
        data.posts.edges.length > 0 ? (
        data.posts.edges.map(slugs => {
            return slugs !== null &&
                slugs.node !== null &&
                slugs.node.slug !== null &&
                slugs.node.title !== null ? (
                <>
                    <Link href={`/articles/${slugs.node.slug}`} passHref key={slugs.node.id}>
                        <a {...props}>
                            {slugs.node.title}
                        </a>
                    </Link>
                </>
            ) : (
                <div>{'Slug or Title Null'}</div>
            )
        })
    ) : (
        <div>
            {
                'data from getAllProfiles either null, undefined, and/or has an edges.length = 0'
            }
        </div>
    );
};

export default resolveProfileSlugs;

I use next/typescript for all my wpgraphql projects. Feel free to poke around my most recent repo -- https://github.com/DopamineDriven/drisdell-consulting-services

Upvotes: 1

Related Questions