Home > Blockchain >  Next.js saving id passed from next/Link
Next.js saving id passed from next/Link

Time:12-15

I am having some issues with the way I currently have the flow set up. I have a component ArticeList that is listening to articles and when clicking on it it will redirect you to the individual article page. I am using next/Link to redirect the article to its landing page and passing the id as a hidden query using the Link attribute as for example:

<Link href={`/article/${ConvertTitleToURL(data.name)}/?id=${data.id}`} as={`/article/${ConvertTitleToURL(data.name)}`}> 

I am then using next/router on my [...article].js page to get the hidden id and use it fetch the article content. For example:

     const router = useRouter()
        const articleId = router.query.id
    
    const apiURL = 'https://test.api/'   id

const { data, error } = useSWR(`${apiURL}`, fetcher)

I am able to successfully make this call with the way it's currently set up but my issue is if the user refreshes the page the id that was originally passed from Link is now loss and I get an error because articleId equals nothing.

Is it possible to save the article id on the first load so if a user refreshes the page the content will still load?

I've attempted to solve this issue by using a react hook but I am still receiving the same error. How can I work around this?

Here is my code sample:

ArticleList component which links passing the id

import Link from 'next/link'

    function ConvertCodeTitleToURL(title) {
        let url = ""
    
        if (title) {
            url = title.replace(".","").toLowerCase()
            url = url.replace(/,/g, "")
            url = url.replace("(", "")     // added for (except) cases
            url = url.replace(/\s/g, "-")
        } else {
            url = "/"
        }
        
        return url
    }
    
    
    const ArticleList = ({articles}) => {
        
        return (
        <div className="container-1200">
                {articles && articles.map(data => (
                    <div key={data.id}> 
                {data.results.length > 0 && 
            <div key={data.id}> 
                <div  className="d-flex justify-space-between">
                <div className="heading-30 letter-spacing-25 text-dark-blue m-l-n-20">{data.name}</div>
                <Link href={`/articles/${ConvertCodeTitleToURL(data.name)}/?id=${data.id}`} as={`/articles/${ConvertCodeTitleToURL(data.name)}`}> 
                </Link>
                 </div>
            </div>
                            }
                            </div>
                ))}
        </div>
    )
        }
    export default ArticleList

article page which is using the id passed from Link to fetch data

import React, { useState } from 'react';
import useSWR from 'swr'
import { useRouter } from 'next/router';
import ArticleLayout from '../../components/ArticleLayout';

const fetcher = (...args) => fetch(...args).then(res => res.json())


function Articles() {

    const router = useRouter()
    const articleId = router.query.id

    const [id, setId] = useState(articleId);


    const apiURL = 'https://test.api/'   id

    const { data, error } = useSWR(`${apiURL}`, fetcher)
 
    if (error) return <div>failed to load ...</div>
    if (!data) return <div>loading....</div>

    return (
        <>
        <ArticleLayout article={data}/>
        </>
    )
}


export default Articles

CodePudding user response:

Save / load id from localStorage. Note that it doesn't handle edge cases.

import React, { useState } from 'react';
import useSWR from 'swr'
import { useRouter } from 'next/router';
import ArticleLayout from '../../components/ArticleLayout';

const ISSERVER = typeof window === "undefined";

const fetcher = (...args) => fetch(...args).then(res => res.json())


function Articles() {

    const router = useRouter()
    const [id, setId] = useState(() => {
      const articleId = router.query.id
      if (ISSERVER) return articleId;
      if (articleId) {
         localStorage.set("articleId", articleId);
         return articleId;
      } else {
         return localStorage.get("articleId");
      }
    });


    const apiURL = 'https://test.api/'   id

    const { data, error } = useSWR(`${apiURL}`, fetcher)
 
    if (error) return <div>failed to load ...</div>
    if (!data) return <div>loading....</div>

    return (
        <>
        <ArticleLayout article={data}/>
        </>
    )
}


export default Articles

CodePudding user response:

useRouter take time to load when you reload page. you can do conditinal fetching on useSWR hook

const router = useRouter()
const articleId = router?.query?.id || '' //check if id exist 
const apiURL = 'https://test.api/'   id

//conditional fetching, null means fetch nothing if articleId not true
const { data, error } = useSWR(articleId ?`${apiURL}`:null, fetcher) 
  • Related