Next.js Discord

Discord Forum

How to render conditional api string depending on screen size?

Answered
Dutch posted this in #help-forum
Open in Discord
DutchOP
Im trying to conditionally render a limit for my api depending on the screen size in a server component, atm im getting error "window is not defined" can someone help?

here's my code:

import MovieCardList from '@/components/MovieCardList';
import PaginationControls from '@/components/PaginationControls';
import MovieSearchBar from '@/components/MovieSearchBar';

import { getFilterdMovie } from '@/utils/api';
import MovieDynamicHeading from '@/components/MovieDynamicHeading';
import { Suspense } from 'react';
import Loader from '@/components/Loader';

export default async function MoviePage({ searchParams }) {
  const defaultLimit = 10;

  const calculateLimit = () => {
    const windowWidth = window.innerWidth;

    if (windowWidth >= 3248) return 20;
    if (windowWidth > 2923) return 20;
    if (windowWidth <= 2923 && windowWidth > 2599) return 24;
    if (windowWidth <= 2599 && windowWidth > 2275) return 21;
    if (windowWidth <= 2275 && windowWidth > 1951) return 24;
    if (windowWidth <= 1951 && windowWidth > 1627) return 25;
    if (windowWidth <= 1627 && windowWidth > 1303) return 24;

    return defaultLimit;
  };

  const limit = calculateLimit();

  const { page = '1', order = 'members', status = 'all', search = '', type = 'all', genres = '' } = searchParams;

  const orderParam = `order_by=${order}`;
  const sortParam = '&sort=desc';
  const limitParam = `&limit=${limit}`;
  const statusParam = status && status !== 'all' ? `&status=${status}` : '';
  const pageParam = `&page=${page}`;
  const searchParam = search ? `&q=${search}` : '';
  const typeParam = type !== 'all' ? `&type=${type}` : '';
  const genreParam = genres ? `&genres=${genres}` : '';
  const params = `${orderParam}${sortParam}${limitParam}${statusParam}${pageParam}${searchParam}${typeParam}${genreParam}&sfw`;
  const data = await getFilterdMovie(params);

  return (
    <div className='px-4 pt-32'>
      <MovieDynamicHeading data={data} order={order} status={status} search={search} type={type} genres={genres} />
      <Suspense fallback={<Loader />}>
        <MovieSearchBar order={order} status={status} search={search} type={type} genres={genres} />
      </Suspense>
      <MovieCardList data={data?.data} limit={limit} />
      <Suspense fallback={<Loader />}>
        <PaginationControls pagination={data?.pagination} />
      </Suspense>
    </div>
  );
}


thank you!
Answered by Ray
It is because the page will be rendered on the server and window is not available.
Could you try to do the calculation in a useEffect?
View full answer

12 Replies

@Dutch Im trying to conditionally render a limit for my api depending on the screen size in a server component, atm im getting error "window is not defined" can someone help? here's my code: import MovieCardList from '@/components/MovieCardList'; import PaginationControls from '@/components/PaginationControls'; import MovieSearchBar from '@/components/MovieSearchBar'; import { getFilterdMovie } from '@/utils/api'; import MovieDynamicHeading from '@/components/MovieDynamicHeading'; import { Suspense } from 'react'; import Loader from '@/components/Loader'; export default async function MoviePage({ searchParams }) { const defaultLimit = 10; const calculateLimit = () => { const windowWidth = window.innerWidth; if (windowWidth >= 3248) return 20; if (windowWidth > 2923) return 20; if (windowWidth <= 2923 && windowWidth > 2599) return 24; if (windowWidth <= 2599 && windowWidth > 2275) return 21; if (windowWidth <= 2275 && windowWidth > 1951) return 24; if (windowWidth <= 1951 && windowWidth > 1627) return 25; if (windowWidth <= 1627 && windowWidth > 1303) return 24; return defaultLimit; }; const limit = calculateLimit(); const { page = '1', order = 'members', status = 'all', search = '', type = 'all', genres = '' } = searchParams; const orderParam = `order_by=${order}`; const sortParam = '&sort=desc'; const limitParam = `&limit=${limit}`; const statusParam = status && status !== 'all' ? `&status=${status}` : ''; const pageParam = `&page=${page}`; const searchParam = search ? `&q=${search}` : ''; const typeParam = type !== 'all' ? `&type=${type}` : ''; const genreParam = genres ? `&genres=${genres}` : ''; const params = `${orderParam}${sortParam}${limitParam}${statusParam}${pageParam}${searchParam}${typeParam}${genreParam}&sfw`; const data = await getFilterdMovie(params); return ( <div className='px-4 pt-32'> <MovieDynamicHeading data={data} order={order} status={status} search={search} type={type} genres={genres} /> <Suspense fallback={<Loader />}> <MovieSearchBar order={order} status={status} search={search} type={type} genres={genres} /> </Suspense> <MovieCardList data={data?.data} limit={limit} /> <Suspense fallback={<Loader />}> <PaginationControls pagination={data?.pagination} /> </Suspense> </div> ); } thank you!
It is because the page will be rendered on the server and window is not available.
Could you try to do the calculation in a useEffect?
Answer
or try this
  const calculateLimit = () => {
    if (typeof window === "undefined") return defaultLimit;

    const windowWidth = window.innerWidth;

    if (windowWidth >= 3248) return 20;
    if (windowWidth > 2923) return 20;
    if (windowWidth <= 2923 && windowWidth > 2599) return 24;
    if (windowWidth <= 2599 && windowWidth > 2275) return 21;
    if (windowWidth <= 2275 && windowWidth > 1951) return 24;
    if (windowWidth <= 1951 && windowWidth > 1627) return 25;
    if (windowWidth <= 1627 && windowWidth > 1303) return 24;

    return defaultLimit;
  };
@Dutch So i should make the whole page.js file 'use client'; ?
For your case, I think this should work
ah but might get hydration error
@Ray For your case, I think this should work
DutchOP
was hoping to find a way to avoid it as im using await for fetching and stuff
i appreciate the help tho
@Dutch this doesnt work, it always returns defaultLimit
you would need useEffect with this then
DutchOP
👍
it's impossible to know the screen width on the server
just fetch the same number of items for all viewports, then use css/client side js to determine how many items are displayed based on screen size