Quantcast
Channel: Active questions tagged youtube-api - Stack Overflow
Viewing all articles
Browse latest Browse all 3831

In Next.js version 13, how do I pass a prop to a component in the root layout if root layout must always be a server-side component?

$
0
0

I'm looking for some help. I'm trying to build a component in Next.js version 13 that plays music in a SongPlayer component positioned at the bottom of the window, much like Spotify's song player, except my SongPlayer component takes a youtubeVideoId prop and uses it to render a youtube iframe embed to play music. I've placed this SongPlayer component in the root layout of my app (app/layout.tsx) because I want the song player to persist between navigating to different pages, and this works, but I also want it to switch which song it plays when a user presses a button from the song page located in app/[songSlug]/page.tsx which updates the youtubeVideoId depending on which url slug the user requests.This is where I get stuck. I think the button on the song page needs to pass the data about which youtubeVideoId that the SongPlayer component should use but the SongPlayer component is a parent component higher up in the component hierarchy. Additionally, because I'm using the Next.js version 13's app directory, the server-side components prevent me from using any react hooks such as useContext.

Here is my code:app/layout.tsx (This is the root layout, which must always be a server-side component.)

import './theme.scss'import './page.scss'import SongPlayer from './components/SongPlayer'// import Play from './components/Play'export const metadata = {  title: 'The Second Messenger',  description: 'Home Page',}export default function RootLayout({  children,}: {  children: React.ReactNode}) {  return (<html lang='en'><body>        {children}<SongPlayer youTubeVideoId={'O94ESaJtHtM'} /></body></html>  )}

app/SongPlayer.tsx

import selectors from './SongPlayer.module.scss'type SongPlayerProps = {  youTubeVideoId: string}export default function SongPlayer({ youTubeVideoId }: SongPlayerProps) {  const srcURL = `https://www.youtube.com/embed/${youTubeVideoId}?color=white&rel=0`  return (<section id={selectors.song_player}><div className={selectors.viewport}><iframe          id='ytplayer'          data-type='text/html'          src={srcURL}          frameBorder='0'          allow='accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture'          allowFullScreen></iframe></div></section>  )}

app/[songSlug]/page.tsx

import { getSongBySlug } from '@/lib/firebase'export default async function SongPage({  params,}: {  params: { songSlug: string }}) {  const song: any = await getSongBySlug(params.songSlug)  const youtubeVideoId = song.stream_links.youtube  return (<main><h2>About {song.title}</h2>      {/* This button should somehow pass youtubeVideoId to SongPlayer component when clicked */}<button onClick={ } >         Play Song</button></main>  )}

Update to add more context about my project:

So this is a website for my music/band. There are several pages, home, music, videos, etc that a user might navigate to as well as the [songSlug] page that shows details of a singular song/release. I want to have streams coming from YouTube so that it will count those video plays on YouTube, so I'm not using html <audio> tags. I've gotten pretty comfortable working with the YouTube API and at some point in the future, I may want to add player controls for a more audio-focused UI but just for now I've simplified the component to just play back a video from YouTube in an absolute-positioned div placed at the bottom-right corner of the screen.I have a CMS that stores data in firebase. This database is where the youtubeVideoId comes from. The idea is that when the user navigates to the [songSlug] page, the page component fetches the data directly from firebase for that specific song based on the slug parameter. Then renders the page with that song's fetched data, such as artwork, comments, outside links, related tracks etc. All the songs in the CMS/database render to the [songSlug]/page.tsx component and have the same layout including a "play this song" button that should somehow tell the SongPlayer component in the root layout, which song to play. The SongPlayer itself is not located inside of the [songSlug] page because I want it to continue to play if the user navigates to any other pages on the site.

To recap:

  1. I place data about each song, including it's slug and it's youtubeVideoId into a firebase database via a CMS.
  2. A user navigates to a page for a specific song, such as mysite.com/music/best-song-ever
  3. The [songSlug]/page.tsx component recognizes the slug parameter ("best-song-ever") and matches it to the slug I inputed for that song in step one and gets all the data in the database for that song, including it's youtubeVideoId
  4. The render method of [songSlug]/page.tsx populates the front end using the data fetched in the last step. This should include a button to play the song (really a YouTube video) for song the user is currently viewing.
  5. The user clicks the play button and the SongPlayer component pops up in the bottom right corner and plays the YouTube video associated with the youtubeVideoId it fetched in step 3 and the user can listen to the song (or watch it's video) while they continue to navigate the site.

Viewing all articles
Browse latest Browse all 3831

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>