app.js 如何更新react-jinke-music-player 里面的播放列表

How to update playlist of react-jinke-music-player inside in app.js

我正在使用 react-jinke-music-player 播放 mp3 文件。如果我的 mp3 列表和播放器在同一页面上,它工作正常。 如果我更改另一个页面,音乐播放器将停止。符合预期。

因此,我使用 React.createContext()app.js 的应用级别添加播放器,如下所示。

我认为全局变量已更新,但 play 的播放列表未更新。

请问如何更新不在同一页面的播放器的播放列表。

app_context.js

import React from 'react';

const AppContext = React.createContext();

export default AppContext;

app.js

import React, { useState } from 'react';
import { Toaster } from 'react-hot-toast';
import Header from './components/header';
import SideMenu from './components/side_menu';
import AppRoutes from './routes';
import { AuthProvider } from './auth/auth_provider';
import withUser from './hocs/with_user';
import ReactJkMusicPlayer from 'react-jinke-music-player';
import 'react-jinke-music-player/assets/index.css';
import options from '../src/constants/autio_player';
import AppContext from './components/app_context';

function App(props) {
  const [playerOptions, setPlayerOptions] = useState(options);
  const [sideBarFull] = useState(true);

  const userSettings = {
    playerOptions,
    setPlayerOptions,
  };

  const PageHeader = () => {
    return (
      <div
        className="h-[72px] w-full flex items-center align-middle justify-center 
     bg-neutral shadow"
      >
        <div className="w-full text-center">
          <Header />
        </div>
      </div>
    );
  };

  return (
    <AuthProvider user={props.user}>
      <AppContext.Provider value={userSettings}>
        <div className="relative w-full min-h-screen min-w-[480px] h-full">
          <div className="flex flex-row min-h-screen">
            <div className="w-auto z-0 ">
              <div className="flex-1 w-full max-h-screen mx-auto text-lg h-full shadow-lg bg-white overflow-y-auto">
                <SideMenu showFullMenu={sideBarFull} />
              </div>
            </div>
            <div className="w-full max-h-screen flex flex-col z-10">
              <PageHeader />
              <div className="flex-1 w-full max-h-screen mx-auto text-lg h-full shadow-lg bg-white overflow-y-auto">
                <Toaster />
                <AppRoutes />
                <ReactJkMusicPlayer {...playerOptions} />
              </div>
            </div>
          </div>
        </div>
      </AppContext.Provider>
    </AuthProvider>
  );
}

export default withUser(App);

playlist.js

const myContext = useContext(AppContext);
options.audioLists = playlist;
myContext.setPlayerOptions(options);

在您的 App 组件中,您正在创建状态,该状态使用 const [playerOptions, setOptions] = useState(options)

保存玩家的选项

options 是你的 initialOptions(你也可以这样命名)。

接下来,您将 optionssetOptions 作为值传递给您的 AppContext.Provider。然后选项和 setter 可以被其他组件使用。

您可以将以下代码片段放在单独的模块中并导出 AppContext 和提供程序。 (在下面的代码和 Codesandbox 中,所有内容都在一个文件中。)

另外创建一个 useAppContextusePlayerContext 挂钩可能会很有趣,如果你有很多地方都在使用它。

const AppContext = createContext({
  options,
  setOptions: () => {}
});

<AppContext.Provider value={{options: playerOptions, setOptions}}>
  <SideMenu/>
</AppContext.Provider>

此处的“特殊性”是您在使用 App 组件的任何地方都使用了 setOptions 引用。 所以它正在改变你的应用程序的状态。

现在,在 SideMenu 组件中,您可以使用 const {options, setOptions} = useContext(AppContext) 获取上下文并使用 setOptions 方法更改选项。 请小心保留其他选项并始终将它们合并为:setOptions({...options, audioLists: newAudiolist})(否则您可能会在不注意的情况下意外丢失一些选项)

您可以选择添加检查上下文是否定义为

const context = useContext(AppContext)
if (context === undefined) {
    throw new Error("AppContext was used outside of its Provider");
}

演示代码:

抱歉,下面的代码片段在这里不起作用,但您可以在 Codesandbox 上查看。

const { useState, createContext, useContext } = React;
//import ReactJkMusicPlayer from "react-jinke-music-player";
//import "./styles.css";
//import "react-jinke-music-player/assets/index.css";

const audioList1 = [
  {
    name: "Despacito",
    singer: "Luis Fonsi",
    cover:
      "http://res.cloudinary.com/alick/image/upload/v1502689731/Despacito_uvolhp.jpg",
    musicSrc:
      "http://res.cloudinary.com/alick/video/upload/v1502689683/Luis_Fonsi_-_Despacito_ft._Daddy_Yankee_uyvqw9.mp3"
    // support async fetch music src. eg.
    // musicSrc: async () => {
    //   return await fetch('/api')
    // },
  },
  {
    name: "Dorost Nemisham",
    singer: "Sirvan Khosravi",
    cover:
      "https://res.cloudinary.com/ehsanahmadi/image/upload/v1573758778/Sirvan-Khosravi-Dorost-Nemisham_glicks.jpg",
    musicSrc:
      "https://res.cloudinary.com/ehsanahmadi/video/upload/v1573550770/Sirvan-Khosravi-Dorost-Nemisham-128_kb8urq.mp3"
  }
];

const audioList2 = [
  {
    name: "Bedtime Stories",
    singer: "Jay Chou",
    cover:
      "http://res.cloudinary.com/alick/image/upload/v1502375978/bedtime_stories_bywggz.jpg",
    musicSrc:
      "http://res.cloudinary.com/alick/video/upload/v1502375674/Bedtime_Stories.mp3"
  }
];

const audioList3 = [
  {
    name: "Despacito",
    singer: "Luis Fonsi",
    cover:
      "http://res.cloudinary.com/alick/image/upload/v1502689731/Despacito_uvolhp.jpg",
    musicSrc:
      "http://res.cloudinary.com/alick/video/upload/v1502689683/Luis_Fonsi_-_Despacito_ft._Daddy_Yankee_uyvqw9.mp3"
  },
  {
    name: "Bedtime Stories",
    singer: "Jay Chou",
    cover:
      "http://res.cloudinary.com/alick/image/upload/v1502375978/bedtime_stories_bywggz.jpg",
    musicSrc:
      "http://res.cloudinary.com/alick/video/upload/v1502375674/Bedtime_Stories.mp3"
  },
  {
    name: "Dorost Nemisham",
    singer: "Sirvan Khosravi",
    cover:
      "https://res.cloudinary.com/ehsanahmadi/image/upload/v1573758778/Sirvan-Khosravi-Dorost-Nemisham_glicks.jpg",
    musicSrc:
      "https://res.cloudinary.com/ehsanahmadi/video/upload/v1573550770/Sirvan-Khosravi-Dorost-Nemisham-128_kb8urq.mp3"
  }
];

const options = {
  audioLists: audioList1,
  clearPriorAudioLists: true
};

const SideMenu = () => {
  const { options, setOptions } = useContext(AppContext);

  // nit check if Sidemenu is inside AppContext - omitted here
  return (
    <div style={{ marginTop: "100px" }}>
      <h2>SideMenu</h2>
      <button
        onClick={() => setOptions({ ...options, audioLists: audioList1 })}>
        Playlist1
      </button>
      <button
        onClick={() => setOptions({ ...options, audioLists: audioList2 })}>
        Playlist2
      </button>
      <button
        onClick={() => setOptions({ ...options, audioLists: audioList3 })}>
        Playlist3
      </button>
    </div>
  );
};

const AppContext = createContext({
  options,
  setOptions: () => {}
});

function App(props) {
  const [playerOptions, setPlayerOptions] = useState(options);
  const [sideBarFull] = useState(true);

  const userSettings = {
    playerOptions,
    setPlayerOptions
  };

  /*const PageHeader = () => {
    return (
      <div className="h-[72px] w-full flex items-center align-middle justify-center 
 bg-neutral shadow">
    <div className="w-full text-center">
      <Header />
    </div>
  </div>
);
  };*/

  return (
    <AppContext.Provider
      value={{ options: playerOptions, setOptions: setPlayerOptions }}
    >
      <div className="relative w-full min-h-screen min-w-[480px] h-full">
        <div className="flex flex-row min-h-screen">
          <div className="w-auto z-0 ">
            <div className="flex-1 w-full max-h-screen mx-auto text-lg h-full shadow-lg bg-white overflow-y-auto">
              <SideMenu showFullMenu={sideBarFull} />
            </div>
          </div>
          <div className="w-full max-h-screen flex flex-col z-10">
            {/*<PageHeader />*/}
            <div className="flex-1 w-full max-h-screen mx-auto text-lg h-full shadow-lg bg-white overflow-y-auto">
              {/*<AppRoutes />*/}
              <ReactJkMusicPlayer {...playerOptions} />
            </div>
          </div>
        </div>
      </div>
    </AppContext.Provider>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(
    <App />,
  rootElement
);
<script src="https://cdn.jsdelivr.net/npm/react-jinke-music-player@4.24.2/lib/index.min.js"></script>
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/react-jinke-music-player@4.24.2/assets/index.css">

<div id="root"></div>