mobix
mobix

Reputation: 515

How to shorten url from Next JS

In my Next js app I'm Passing an Object through pages. what I did is compress my array of objects into JSON JSON.stringify(result) from index page and in my second page I parsed it JSON.parse(props.router.query.result). this worked great. but the issue is when reloading the page the browser prompts

This page isn’t workingIf the problem continues, contact the site owner.
HTTP ERROR 431

I know this message indicates for long url head. so is there a way for me to shorten this?

index page

<Link href=
   {{pathname: "/tv-shows",
   query: {
   result: JSON.stringify(result),
   //result: [result],
   img: img,
   index: index,
  }}} key={index}
  >
  <div className=' relative snap-center h-56 w-96 rounded-3xl hover:rounded-3xl hover:scale-110 hover:transition-all hover:duration-200 hover:ease-in ease-out duration-200 '>
    <Image 
       src={img}
       layout="fill"
       objectFit="cover"
       className={`h-full w-full bg-cover bg-no-repeat rounded-3xl hover:rounded-3xl hover:scale-110 hover:transition-all hover:duration-200 hover:ease-in ease-out duration-200`} />
 </div></Link>

in second page

const TvShows = (props) => {
  const [result, setResult] = useState([]);
  const [index, setIndex] = useState("");
  const [img, setImg] = useState("");
  
    useEffect(()=>{
      console.log("first")
      console.log(props.router.query);
      if (props.router.query.result){
        const query = props.router.query;
        const res = JSON.parse(query.result);
        setResult(res);
        setIndex(query.index);
        setImg(query.img);
        //console.log(JSON.parse(props.router.query.result));
      }
      
           
    },[props.router.query ])


  return (
    <div className=''>
      <Head>
        <title>{Popular[Number(index)].title} |  </title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <Background result={result} img={img} index={index} />
      {/* <Background img={img} index={index} /> */}
      <div className='cursor-default px-10'>
        <div className=' text-xl pt-5 pb-5'>Full Episodes </div>
        {/* <Contents result={result} index={index}/> */}
      </div>
      
    </div>
  )
}

export default withRouter(TvShows)

please help me with the fix

Upvotes: 0

Views: 1199

Answers (1)

deaponn
deaponn

Reputation: 858

Based on comments to your original post, I deducted that you do not want to shorten a very long URL, but you are trying to pass data between subpages of Next app and save it so it is accessible after page refresh. What you can do to solve your issue is saving your result to localStorage every time it changes:

useEffect(() => {
    localStorage.setItem("result", JSON.stringify(result))
}, [result])

And then, in your second page read the data:

useEffect(()=>{
    const result = JSON.parse(localStorage.getItem("result"))
    console.log("first")
    console.log(result);
    if (result){
        setResult(result);
        setIndex(query.index);
        setImg(query.img);
    }  
}, [])

After comments to this Answer:

I think that what you want to do is creating a page tv-shows, which will display the details of one Youtube playlist. Best way to get this working is by creating dynamic routes.

Create the following directory structure in your app:

root
└── pages
    └── tv-shows
        └── [index].js

Paste this into the file [index].js

import { useRouter } from "next/router";

export async function getStaticPaths() {
    return {
        paths: [{ params: { index: "0" } }, { params: { index: "1" } }],
        fallback: false
    };
}

export async function getStaticProps(context) {
    const MY_PLAYLIST_1 = "PL9562CjMJkXIgaV_UA5hf1VADfn4Sqd0P";
    const MY_PLAYLIST_2 = "PL9562CjMJkXIgaV_UA5hf1VADfn4Sqd0P";
    const API_KEY = "AIzaSyCELe0KoZYBjonJskBMbzdlTuCow3sr3zo";

    const PLAYLIST_REQUEST_URL_1 = `https://youtube.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=500&playlistId=${MY_PLAYLIST_1}&key=${API_KEY}`;
    const PLAYLIST_REQUEST_URL_2 = `https://youtube.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=500&playlistId=${MY_PLAYLIST_2}&key=${API_KEY}`;
    const playlistResponse1 = await fetch(PLAYLIST_REQUEST_URL_1);
    const playlistResponse2 = await fetch(PLAYLIST_REQUEST_URL_2);
    const playlistResult1 = await playlistResponse1.json();
    const playlistResult2 = await playlistResponse2.json();
    return {
        props: {
            results: [playlistResult1, playlistResult2],
        },
        revalidate: 3600,
    };
}

export default function TvShows({results}) {
    const router = useRouter();
    const { index } = router.query;

    return <div>{index}, {JSON.stringify(results[index])}</div>;
}

Next step, override content of card.js with the following (just remove result variable and the query parameter)

import Link from "next/link";

const Card = ({ index }) => {
    return (
        <nav>
            <Link
                href={`/tv-shows/${index}`}
            >
                <div>
                    <h1>card click</h1>
                </div>
            </Link>
        </nav>
    );
};
export default Card;

Override index.js to remove unnecessary API calling code and take new card.js's props into account:

import Link from "next/link";
import Card from "../comps/card";
import Popular from "../comps/popular";

export default function IndexPage() {
  return (
    <div>
      Hello World. {/* <Link href="/about">
        <a>About</a>
      </Link> */}
      <Card index={0} img={Popular[0].img} />
      <Card index={1} img={Popular[1].img} />
    </div>
  );
}

How the solution works is as follows:

We create dynamic routes which takes only query parameter index of our playlist. Every index parameter that is possible to be set is defined in paths: [{ params: { index: "0" } }, { params: { index: "1" } }]. These path params are then passed to our dynamic route which is then pre-rendered, and downloading all the data only once. And finally, our route displays data based on query parameters supplied by useRouter.

Upvotes: 2

Related Questions