NextJS 14 – loading.tsx component not rendering loading animation as a get request is being filled

My page.tsx component which loads 500 photos:

'use client';
import { useEffect, useState } from 'react';
import { wait } from '@/components/loaders/skeletons';

export default function Postings() {
  const [photos, setPhotos] = useState([]);

  const fetchMockPhotos = async () => {
    try {
      const response = await fetch(
        'https://jsonplaceholder.typicode.com/photos'
      );

      await wait(2000);

      const data = await response.json();
      console.log('fetching mock photos data:', data);
      setPhotos(data);
    } catch (error: any) {
      console.error(error);
    }
  };

  useEffect(() => {
    fetchMockPhotos();
  }, []);

  return (
    <>
      {photos.length === 0 && (
        <div className="skeleton">Hello Postings View...</div>
      )}
      
      <div>
        {photos &&
          photos.map((photo: any) => (
            <img key={photo.id} src={photo.url} alt={photo.title} />
          ))}
      </div>
    </>
  );
}

My loading.tsx, in the same directory as the /postings/page.tsx above:

import React from 'react';

const Loading: React.FC = () => {
  return (
    <div className="loading-container">
      <div className="loading-spinner"></div>
      <p>Loading...</p>
    </div>
  );
};

export default Loading;

The layout.tsx

import type { Metadata } from 'next';
import { Suspense } from 'react';

import Loading from './loading';

export const metadata: Metadata = {
  title: 'Company | Postings',
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <>
      <Suspense fallback={<Loading />}>{children}</Suspense>
    </>
  );
}

I’ve also tried writing the layout.tsx like so:

import type { Metadata } from 'next';
import { FC, ReactNode, Suspense } from 'react';

import Loading from './loading';

interface layoutProps {
  children: ReactNode;
}

export const metadata: Metadata = {
  title: 'Company | Postings',
};

const Layout: FC<layoutProps> = ({ children }) => {
  return (
    <>
      <Suspense fallback={<Loading />}>{children}</Suspense>
    </>
  );
};

export default Layout;

Styles for the loader:

.skeleton {
  position: relative;
  top: 25rem;
  left: 25rem;
}

.red-button-skeleton {
  display: block;
  width: 310px;
  height: 52px;
  border-radius: 8px;
  background-color: rgba(208, 2, 27, 0.25); /* Red color with 25% opacity */
}

.loading-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
}

.loading-spinner {
  border: 4px solid rgba(0, 0, 0, 0.1);
  border-left-color: #333;
  border-radius: 50%;
  width: 50px;
  height: 50px;
  animation: spin 1s linear infinite;
}

The Loader never displays as I refresh the page.

Folder directory:

enter image description here

Screen recording:

https://www.youtube.com/watch?v=K5nphIY7A5k

What I’ve also tried:

Also did not render the loading animation.

exported out a default function called Loading from the loading.tsx file:

import LoadingSkeleton from '@/components/loaders/loading-skeleton';

export default function Loading() {
  // You can add any UI inside Loading, including a Skeleton.
  return <LoadingSkeleton />;
}

And the LoadingSkeleton component

import React from 'react';

const LoadingSkeleton: React.FC = () => {
  return (
    <div className="loading-container">
      <div className="loading-spinner"></div>
      <p>Loading...</p>
    </div>
  );
};

export default LoadingSkeleton;