skip to Main Content

I have given a code to implement music player using context.
Below is the source code:

import React from 'react';
import {
  BarSongTitle,
  BottomBar,
  Button,
  PlayList,
  Song,
  SongTitle,
} from './styles.js';
import { songList } from './constants.js';

const buttonLabels = ['Not replaying', 'Replaying all', 'Replaying one'];

const PlayerProvider = ({ children }) => {
  return children;
};

const usePlayerContext = () => {};

const ControlBar = () => {
  const title = 'test - song';
  return (
    <BottomBar>
      <BarSongTitle data-testid="barTitle">{title}</BarSongTitle>
      <div>
        <Button data-testid="previousButton">Previous</Button>
        <Button data-testid="nextButton">Next</Button>
        <Button data-testid="currentModeButton">{'replay mode'}</Button>
      </div>
    </BottomBar>
  );
};

const Songs = () => {

  const[currentSong, setCurrSongSel] = React.useState('');

  return (
    <PlayList>
      {songList.map(({ title, author, id }) => (
        <Song key={id} onClick={()=> setCurrSongSel(id)}>
          <SongTitle data-testid={id} active={currentSong === id ? true : false}>
            {title}
          </SongTitle>
          <p>{author}</p>
        </Song>
      ))}
    </PlayList>
  );
};

export { PlayerProvider, Songs, ControlBar };

I need to pass the data of currentSong from Songs component to ControlBar component using context (PlayerProvider or usePlayerContext). Can someone know how?

This is the code for App.js(we can’t make any change to that):

<PlayerProvider>
  <main data-test-id="mainPart">
    <Songs/>
    <ControlBar/>
  </main>
</PlayerProvider>

I am new to hooks and context concept, so don’t know where to go from here.

2

Answers


  1. you can initialized context value in PlayerProvider and pass context value in usePlayerContext. I hope this useful for you.

    import React from 'react';
    import {
      BarSongTitle,
      BottomBar,
      Button,
      PlayList,
      Song,
      SongTitle,
    } from './styles.js';
    import { songList } from './constants.js';
    
    const PlayerContext = React.createContext();
    
    const buttonLabels = ['Not replaying', 'Replaying all', 'Replaying one'];
    
    const PlayerProvider = ({ children }) => {
      const [currentSong, setCurrentSong] = React.useState('');
      
      const updateCurrentSong = React.useCallback((id) => {
        setCurrentSong(id);
      }, []);
    
      return (
        <PlayerContext.Provider value={{ currentSong, updateCurrentSong }}>
          {children}
        </PlayerContext.Provider>
      );
    };
    
    const usePlayerContext = () => {
      const context = React.useContext(PlayerContext);
      if (!context) {
        throw new Error('usePlayerContext used within PlayerProvider');
      }
      return context;
    };
    
    const ControlBar = () => {
      const { currentSong } = usePlayerContext();
      const title = songList.find(song => song.id === currentSong)?.title || 'test - song';
      
      return (
        <BottomBar>
          <BarSongTitle data-testid="barTitle">{title}</BarSongTitle>
          <div>
            <Button data-testid="previousButton">Previous</Button>
            <Button data-testid="nextButton">Next</Button>
            <Button data-testid="currentModeButton">{'replay mode'}</Button>
          </div>
        </BottomBar>
      );
    };
    
    const Songs = () => {
      const { updateCurrentSong } = usePlayerContext();
    
      return (
        <PlayList>
          {songList.map(({ title, author, id }) => (
            <Song key={id} onClick={() => updateCurrentSong(id)}>
              <SongTitle data-testid={id}>
                {title}
              </SongTitle>
              <p>{author}</p>
            </Song>
          ))}
        </PlayList>
      );
    };
    
    export { PlayerProvider, Songs, ControlBar };

    You can initialized value in PlayerProvider

    Login or Signup to reply.
  2. To pass the data of currentSong from the Songs component to the ControlBar component using context, you need to create a context using React.createContext() and provide the context value using PlayerProvider. Then you can consume the context value using the usePlayerContext hook in both the Songs and ControlBar components. Here’s how you can do it:

    1. Create a context called PlayerContext.
    const PlayerContext = React.createContext();
    
    1. Modify the PlayerProvider to provide the PlayerContext with a value.
    const PlayerProvider = ({ children }) => {
      const [currentSong, setCurrentSong] = React.useState(null);
    
      const value = {
        currentSong,
        setCurrentSong,
      };
    
      return <PlayerContext.Provider value={value}>{children}</PlayerContext.Provider>;
    };` 
    
    1. Create the usePlayerContext hook to consume the PlayerContext.
    const usePlayerContext = () => {
      const context = React.useContext(PlayerContext);
    
      if (context === undefined) {
        throw new Error("usePlayerContext must be used within a PlayerProvider");
      }
    
      return context;
    };
    
    1. Modify the Songs component to use the usePlayerContext hook.
    const Songs = () => {
      const { currentSong, setCurrentSong } = usePlayerContext();
    
      return (
        <PlayList>
          {songList.map(({ title, author, id }) => (
            <Song key={id} onClick={() => setCurrentSong(id)}>
              <SongTitle data-testid={id} active={currentSong === id ? true : false}>
                {title}
              </SongTitle>
              <p>{author}</p>
            </Song>
          ))}
        </PlayList>
      );
    };` 
    
    1. Modify the ControlBar component to use the usePlayerContext hook.
    const ControlBar = () => {
      const { currentSong } = usePlayerContext();
      const title = currentSong ? songList.find(song => song.id === currentSong).title : 'No song selected';
    
      return (
        <BottomBar>
          <BarSongTitle data-testid="barTitle">{title}</BarSongTitle>
          <div>
            <Button data-testid="previousButton">Previous</Button>
            <Button data-testid="nextButton">Next</Button>
            <Button data-testid="currentModeButton">{'replay mode'}</Button>
          </div>
        </BottomBar>
      );
    };` 
    

    With these modifications, the currentSong state will be shared between the Songs and ControlBar components using the context. When you click on a song in the Songs component, the title will be updated in the ControlBar component accordingly.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search