I am making a new react app which have multiple music cards on same page. I want to change the state of previous card before updating the state of new card. In short I want to pause previous audio before playing new one.
import React, { useState , useEffect , useRef} from "react";
import Card from '@mui/material/Card';
import CardContent from '@mui/material/CardContent';
import CardMedia from '@mui/material/CardMedia';
import Typography from '@mui/material/Typography';
import { CardActionArea } from '@mui/material';
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
import IconButton from '@mui/material/IconButton';
import PauseICon from "@mui/icons-material/Pause";
import { logDOM } from "@testing-library/react";
export default function ActionAreaCard(props) {
const audioRef = useRef(new Audio("http://myinstants.org/games/22ecaa5e-f90f-4e81-96b1-b240751439fa.mp3"));
const [clicked, setClicked] = useState(false);
useEffect(() => {
audioRef.current.addEventListener('ended', () => setClicked(false));
if (clicked) {
audioRef.current.play();
} else {
audioRef.current.pause();
}
},[clicked]);
return (
<Card sx={{ maxWidth: 256 }} >
<CardMedia
component="img"
height="140"
image="https://picsum.photos/400/200"
alt="green iguana"
/>
<CardContent style={{ display: 'flex', flexDirection: 'column' }}>
<Typography gutterBottom variant="h5" component="div" style={{ textAlign: 'center', overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }}>
lorem Spem kjb j kl lk n lkn lk nlk n kln lkn kln kln kl nlk n vdr rtgvrt rtwbtr rtbvrt vbwrt vwretvw
</Typography>
{/* <PlayArrowIcon sx={{ height: 38, width: 38}}/> */}
<IconButton onClick={() => setClicked(!clicked)}>
{
clicked ? <PauseICon sx={{ height: 38, width: 38 }} /> : <PlayArrowIcon sx={{ height: 38, width: 38 }} />
}
</IconButton>
</CardContent>
</Card>
);
}
The above one is my playing card component.
The above GIF is the working app. In which when I play the second Audio it starts it before stopping the old when. MY background is from android development in which we have only one object of media player and we can manage this using that object. But here i found no solution may be we can do it by accessing the other component state in an other component or may be using a hook etc.
CodePudding user response:
Make a common state in parent storing active playing:
const [activePlaying,setActivePlaying]=useState(null);
Make a handler for it:
const activePlayerhandler=useCallback((id)=>{
setActivePlaying(id);
},[id]);
Pass this handler as a prop:
...
{players.map((player,index)=>(
< ActionAreaCard onPlay={()=>activePlayerhandler(index)} playing={activePlaying===index}/>
))
...
now you just need to call this prop on play button click.