logo studio roma
EN / ES

Back to Blog

AudioPlayer 2

Pablo Romera foto

Pablo Romera 

/

 July 13, 2023 / 4 min read

Pablo Romera foto

Using React's useContext to manage global state for an AudioPlayer

Managing state in large and complex applications can become a challenging task. React offers an efficient solution to this problem through the use of Context, which allows components to consume and subscribe to context changes. In this article, we will delve into using React's useContext to manage the global state of an AudioPlayer, thoroughly analyzing the code and providing additional comments for a better understanding.

Setting up the AudioPlayer's Context

React Context provides a way to share values like these among components without having to explicitly pass a prop through every level of the component tree.

AudioPlayerContext Component

This component defines the context that we will use throughout our application for the control of the AudioPlayer. We created it to be able to manage and access the player's state (isActive) on all the web pages.

import { createContext, useState } from "react";

// Creating the context
export const AudioPlayerContext = createContext();

export const AudioPlayerProvider = ({ children }) => {
  const [isActive, setIsActive] = useState(false); // Defining the initial state

  const play = () => {
    // Function to play
    setIsActive(true);
  };

  const pause = () => {
    // Function to pause
    setIsActive(false);
  };

  // Providing the state and functions to the child components
  return (
    <AudioPlayerContext.Provider value={{ isActive, play, pause }}>
      {children}
    </AudioPlayerContext.Provider>
  );
};

Here, we have defined two functions, play and pause, which will modify the isActive state of our AudioPlayer. All components wrapped by AudioPlayerProvider will have access to these functions and the current state.

Integration in _app.js

This snippet shows how to wrap our application with the context provider, allowing any component in our application to have access to the context.

import React from "react";
import { AudioPlayerProvider } from "@/components/context/AudioPlayerContext";

// All components inside AudioPlayerProvider will have access to the context
export default function MyApp({ Component, pageProps }) {
  return (
    <AudioPlayerProvider>
      <Component {...pageProps} />
    </AudioPlayerProvider>
  );
}

Developing the Player component

The Player component is responsible for audio playback. This is where React Context really shines, as we can easily access the state and functions provided by our AudioPlayerContext. With the Player component, we will access the player's controls to play, pause, or change the song in the player. Thanks to React Context, the player's state will change and can be accessed from any web page.

Player Component

import React, { useState, useEffect, useRef, useContext } from "react";

import { AudioPlayerContext } from "@/components/context/AudioPlayerContext";
import Controls from "@/components/Controls";

import songList from "@/components/player/songs";

const Player = (props) => {
  const { isActive } = useContext(AudioPlayerContext); // Accessing the context
	const [isPlaying, setIsPlaying] = useState(isActive); // Local state for playback control
	const audioElement = useRef(); // Reference to the audio element
	const [currentSong, setCurrentSong] = useState(songList[randomNumber]);

	...

  useEffect(() => {
    if (!isPlaying) {
      audioElement.current.play(); // Play the audio. Function defined in the context.
    } else {
      audioElement.current.pause(); // Pause the audio. Function defined in the context.
    }
  }, [isPlaying]); // Observing changes in isPlaying

  return (
        <div>
          <Controls
            songList={songList}
            isPlaying={isPlaying}
            setIsPlaying={setIsPlaying}
            currentSong={currentSong}
            setCurrentSong={setCurrentSong}
            audioElement={audioElement}
          />
          <audio
            id="audio-player"
            name="audio-player"
            src={currentSong.url}
            ref={audioElement}
          ></audio>
        </div>
  ); // Returning the player interface
};

export default Player;

Conclusion

Global state management is a crucial part of any modern and complex React application. With useContext, we can simplify this process and write cleaner and reusable code. We have explored how to use this powerful hook to build an audio player, but the possibilities are vast. Understanding and effectively applying these concepts can significantly improve the structure and efficiency of our React projects.