javascript - 在 Next.js 版本 13 中,如果根布局必须始终是服务器端组件,如何将 prop 传递给根布局中的组件?

标签 javascript reactjs next.js react-hooks youtube-api

我正在寻求帮助。我正在尝试在 Next.js 版本 13 中构建一个组件,该组件在位于窗口底部的 SongPlayer 组件中播放音乐,很像 Spotify 的歌曲播放器,但我的 SongPlayer 组件采用 youtubeVideoId Prop 并使用它来渲染 youtube iframe 嵌入来播放音乐。我已将此 SongPlayer 组件放置在我的应用程序 (app/layout.tsx) 的根布局中,因为我希望歌曲播放器在导航到不同页面之间保持不变,这是可行的,但我也希望它切换播放哪首歌曲当用户按下位于 app/[songSlug]/page.tsx 中的歌曲页面中的按钮时,该按钮会根据用户请求的 url slug 更新 youtubeVideoId。 这就是我陷入困境的地方。我认为歌曲页面上的按钮需要传递有关 SongPlayer 组件应使用的 youtubeVideoId 的数据,但 SongPlayer 组件是组件层次结构中较高的父组件。此外,由于我使用的是 Next.js 版本 13 的应用程序目录,因此服务器端组件会阻止我使用任何 React Hook ,例如 useContext。

这是我的代码: app/layout.tsx(这是根布局,它必须始终是服务器端组件。)

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>
  )
}

应用程序/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>
  )
}

应用程序/[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>
  )
}

更新以添加有关我的项目的更多上下文:

这是我的音乐/乐队的网站。用户可以导航到多个页面,例如主页、音乐、视频等,以及显示单个歌曲/发行的详细信息的 [songSlug] 页面。我想要来自 YouTube 的流,以便它能够计算 YouTube 上的视频播放次数,所以我没有使用 html <audio>标签。我已经非常习惯使用 YouTube API,并且在将来的某个时候,我可能想要添加播放器控件以获得更注重音频的 UI,但目前我已经简化了组件,以便仅播放来自YouTube 位于屏幕右下角的绝对定位 div 中。 我有一个 CMS,将数据存储在 firebase 中。这个数据库就是 youtubeVideoId来自。这个想法是,当用户导航到 [songSlug] 页面时,页面组件根据 slug 参数直接从 firebase 获取该特定歌曲的数据。然后使用该歌曲获取的数据(例如插图、评论、外部链接、相关轨道等)渲染页面。CMS/数据库中的所有歌曲都会渲染到 [songSlug]/page.tsx 组件,并具有相同的布局,包括“播放这首歌曲”按钮应该以某种方式告诉根布局中的 SongPlayer 组件要播放哪首歌曲。 SongPlayer 本身并不位于 [songSlug] 页面内部,因为我希望它在用户导航到网站上的任何其他页面时继续播放。

回顾一下:

  1. 我放置了每首歌曲的数据,包括它的歌曲和 youtubeVideoId通过 CMS 导入 Firebase 数据库。
  2. 用户导航到特定歌曲的页面,例如 mysite.com/music/best-song-ever
  3. [songSlug]/page.tsx 组件识别 slug 参数(“best-song-ever”)并将其与我在第一步中为该歌曲输入的 slug 进行匹配,并获取数据库中该歌曲的所有数据,包括 youtubeVideoId
  4. [songSlug]/page.tsx 的 render 方法使用上一步获取的数据填充前端。其中应包含一个按钮,用于播放用户当前正在观看的歌曲(实际上是 YouTube 视频)。
  5. 用户点击播放按钮,SongPlayer 组件会在右下角弹出,并播放与第 3 步中获取的 youtubeVideoId 关联的 YouTube 视频,用户可以在播放歌曲时收听歌曲(或观看其视频)继续浏览网站。

最佳答案

我想您可以使用模板而不是使用文档中列出的布局,如果我们正在工作取决于 useState 或 useEffect,那么它们是更好的选择。我分享一个链接供您引用: 依赖于 useEffect(例如记录页面 View )和 useState(例如每页反馈表)的功能。 https://nextjs.org/docs/app/api-reference/file-conventions/template

关于javascript - 在 Next.js 版本 13 中,如果根布局必须始终是服务器端组件,如何将 prop 传递给根布局中的组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77098854/

相关文章:

javascript - 无法从ajax获取post数据到php

javascript - Selenium Webdriver - 仅具有精确值标识的元素,js/html

javascript - 在 Options API (Vue Js) 中使用 Composition API

node.js - 对服务器和客户端( react )应用程序使用相同的 .env 文件

css - Next.js 应使用什么图像尺寸?

javascript - NextJS,Express,WebSocket 握手期间出错 : Unexpected response code: 200

javascript - CoffeeScript 错误

javascript - redux-thunk 的唯一好处是什么?

javascript - Swiper.js 自动播放的自定义停止和播放按钮(React/Next)

javascript - 将第三方脚本导入 React