Play local audio in React - javascript

I need to play local audio in React using hooks. Application will be deployed later to some server.
Application folder consists of the following:
index.html
index.css
index.js
audio folder with first.mp3 and second.mp3
It looks like this:
I have added screenshot because without CSS it wouldn't we clear what I need to accomplish. (just two simple numbers would be printed in div). Codepen link (with CSS)
So I should play sound when these Box components are clicked.
Here's 'index.js' file:
import React, { useState } from 'react';
import ReactDOM from 'react-dom'
import "./index.css"
const sounds = [
{
key: "1",
mp3: "./audio/first.mp3",
},
{
key: "2",
mp3: "./audio/second.mp3",
}
];
const App = () => {
const [keys, setKeys] = useState([
"1",
"2"
]);
return (
<div id="display" className="display">
{sounds.map((sound, id) => {
return <Box text={sound.key} audio={sound.mp3} />;
})}
</div>
);
};
const playSound=(props)=>{
return(
props.audio.current.play;
)
}
const Box = (props) => {
return (
<div className="box" onClick={playSound(props)}>
{props.text}
<audio src={props.audio} className="clip" id={props.text}/>
</div>
);
};
ReactDOM.render(<App/>, document.getElementById("root"));
Problem here is props.audio.current.play;. It doesn't play the sound.
I tried to console.log(props.audio) and it prints correctly for ex. ./audio/first.mp3
Could you please help me to fix this?

I can help you out by providing a general idea:
let audioEl = new Audio(audioUrl);
// Play
audioEl.play();
// Pause
audioEl.pause();
// Set current time
audioEl.currentTime = 0;

Related

React - audio element not playing - "Uncaught (in promise) DOMException: Failed to load because no supported source was found"

I'm trying to create a drum machine using React but I can't get my audio clips to play via the onClick. I've browsed similar questions but none of them did it for me.
My Github: drum-machine
My code below. I originally had the audio clips in a separate Libs folder, but I've copied and pasted them in the specific component folder (DrumMachine) to see if the issue was related to the path, but it still doesn't work.
Folder structure
Code:
DrumMachine component
import React from 'react';
import './index.css';
import DrumPad from '../DrumPad/index';
export default function DrumMachine(props) {
const keys = ["Q", "W", "E", "A", "S", "D", "Z", "X", "C"];
const elements = ["crash1", "crash2", "hatClosed1", "hatClosed2", "hatOpen1", "hatOpen2", "kick", "snare", "tambourine"];
const audioClips = ["./Crash_1.wav", "./Crash_2.wav", "./Hat_Closed_1.wav", "./Hat_Closed_2.wav", "./Hat_Open_1.wav", "./Hat_Open_2.wav", "./Kick.wav", "./Snare_2.wav", "./Tambourine.wav"];
async function handleClick(e) {
const sound = await new Audio (e);
await sound.play();
}
return (
<section id="drum-machine">
<section id="display">
{keys.map((element, index) => {
console.log(audioClips[index]);
return (
<DrumPad className="drum-pad" id={elements[index]} key={index} text={element} onClick={() => handleClick(audioClips[index])}>
<audio type="audio/WAV" src={audioClips[index]} className="clip" id={element}></audio>
</DrumPad>
)
})}
</section>
</section>
)
}
DrumPad component
import React from 'react';
import './index.css'
export default function DrumPad(props){
const className = props.className;
const id = props.id;
const text = props.text;
const handleClick = props.onClick
return (
<section >
<button id={id} className={className} onClick={handleClick}>
{text}
{props.children}
</button>
</section>
)
}
Appreciate your help.

How to place an icon on an if then statement for a react button

I'm trying to create a button that will display a different icon and message when it is clicked. However, I'm unsure of how to include the icon inside the 'if then' statement within the < button > element. I'm quite new to React.
My code is below:
import React, { setState, useState, useEffect } from "react";
import { Pause,
Play } from 'react-feather';
function AudioPlayer() {
// use Audio constructor to create HTMLAudioElement
const audioTune = new Audio("<YOUR_AUDIO_FILE_PATH.mp3>");
// variable to play audio in loop
const [playInLoop, setPlayInLoop] = useState(false);
// variable to play audio in loop
const [isPlay, isPlaying] = useState(0);
// load audio file on component load
useEffect(() => {
audioTune.load();
}, []);
// play audio sound
const playSound = () => {
audioTune.play();
isPlaying(1);
};
// pause audio sound
const pauseSound = () => {
audioTune.pause();
};
// stop audio sound
const stopSound = () => {
audioTune.pause();
audioTune.currentTime = 0;
isPlaying(0);
};
const handlePlaying = () => {
if (isPlay) {
stopSound();
} else {
playSound();
}
};
return (
<div>
<div className="App">
<button onClick={handlePlaying}>
{isPlay ? <Pause /> "pause" : <Play/> "listen to this page"}
</button>
</div>
</div>
);
}
export default AudioPlayer;
I get an error here {isPlay ? <Pause /> "pause" : <Play/> "listen to this page"}
The error is:
SyntaxError
/src/components/Audio2.js: Unexpected token, expected ":" (57:30)
I've tried to insert the icon within the "" marks, but that is just displaying the button code as string.
Thanks for your help
You can do it like this
<button onClick={handlePlaying}>
{isPlay ? (
<>
<Pause /> Pause
</>
) : (
<>
<Play /> Listen to this page
</>
)}
</button>;

Syntax highlighter not working using codemirror 2 with Next.js

I saw many examples it works fine for all but I don't know why it does not highlight my code.
I tried many solutions none of them work for me.
Also, I need to inject my own custom HTML file in it for the initial when user click on demo for the code and also user can change the file and run its own custom code that user want.
Here is the screenshot of the output:
Code that I used for the editor
import React from 'react';
import {Controlled as ControlledEditor} from 'react-codemirror2';
import {language} from "#hapi/accept";
import {codecs} from "next/dist/next-server/server/lib/squoosh/codecs";
if (typeof navigator !== 'undefined') {
require('codemirror/mode/xml/xml');
require('codemirror/mode/css/css');
require('codemirror/mode/javascript/javascript');
require('codemirror/mode/markdown/markdown');
}
const Editor = (props) => {
const {
displayName,
value,
onChange
} = props
const handleChange = (editor,date,value) => {
onChange(value);
}
return (
<div className="editor-container">
<div className="editor_title">
{displayName}
<button>O/C</button>
</div>
<ControlledEditor
onBeforeChange={handleChange}
value={value}
className={'code-mirror-wrapper'}
options={{
lineWrapping:true,
lint:true,
mode:language,
theme:'dracula',
lineNumbers:true
}}
/>
</div>
)
}
export default Editor;
That is the new file where I call my editor:
import React,{useState,useEffect} from 'react';
import Editor from '../../component/Editor/editor';
const RunCode = () => {
const [html,setHtml] = useState();
const [css,setCss] = useState();
const [JS,setJS] = useState();
const [scrDoc,setSrcDoc] = useState('');
useEffect(()=>{
const timeout = setTimeout(()=>{
setSrcDoc(
`<html>
<body>${html}</body>
<style>${css}</style>
<script>${JS}</script>
</html>`
)
},250)
return () => clearTimeout(timeout)
},[html,JS,css]);
return(
<>
<div className={'pane top-pane'}>
<Editor
language={'xml'}
displayName={'HTML'}
value={html}
onChange={setHtml}
/>
<Editor
language={'CSS'}
displayName={'CSS'}
value={css}
onChange={setCss}
/>
<Editor
language={'JS'}
displayName={'JS'}
value={JS}
onChange={setJS}
/>
</div>
<div className="output">
<iframe
srcDoc={scrDoc}
title={'Output'}
sandbox={'allow-scripts'}
height={'100%'}
width={'100%'}
>
</iframe>
</div>
</>
)
}
export default RunCode;
The short answer is: You might not be importing the .css file to use the "Dracula" theme.
Make sure you are importing these two files from node_modules in the component in which you are using ControlledEditor, to provide the theme to your editor.
import "codemirror/lib/codemirror.css";
import "codemirror/theme/dracula.css";
PS: My personal favorite theme is: ayu-dark ;)
I have also made a similar thing. Here is a Github Repo for your reference. :)
FunFact: #juliomalves helped me in deploying this project on vercel.😁

ReactPlayer make 2 file play in same time

I want to play 2 file in reactjs use ReactPlayer , file 1 is video music include audio human voice , file 2 is music only but the human voice has been deleted.
The problem when I run the code below is file 1 may start sooner than file 2 or vice versa , my question is can I play 2 file together , so when file 1 loading or render , file 2 will do same as file 1
This the code
import React, { useState } from "react";
import ReactPlayer from "react-player";
function App(){
const [playing, setPlaying] = useState(true);
const [muted, setMuted] = useState(true);
function handlePlayPause() {
setPlaying(!playing);
}
function handleMuted() {
setMuted(!muted);
}
return(
<div>
//play video music "I can fly include the music with human vocal"
<ReactPlayer
playing={playing}
url={"I can Fly.mp4"}
muted={muted}
/>
//play music only "I can fly (the file no human vocal)"
<ReactPlayer
playing={playing}
url={"I can fly(no vocal).mp3"}
muted={!muted}
hidden
/>
<button onClick={() => handlePlayPause()}>
{playing ? "pause" : "play"}
</button>
<button onClick={() => handleMuted()}>
{muted ? "vocal" : "no vocal"}
</button>
</div>
)}
export default App;
Hope you guys understand what I'm asking , sorry for my bad English :D
I guess the issue is from a video needs time to get ready before playing. Each video has a different its own time which means each video would have a different time to start playing.
As a result of that, we have to wait until all videos ready before playing them all at once. Luckily, react-player has offered a onReady callback telling that video is ready to play. Here is the general idea for you:
import React from "react";
import ReactPlayer from "react-player";
// Assuming to have 2 videos
const links = [
"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4"
];
export default function App() {
// Count number of videos ready to play
const [readyCount, setReadyCount] = React.useState(0);
const [playing, setPlaying] = React.useState(false);
// Just keep counting as a video ready
const onReady = () => {
setReadyCount(readyCount + 1);
};
React.useEffect(() => {
// All videos ready to play, get them played
if (readyCount === links.length) {
setPlaying(true);
}
}, [readyCount]);
return (
<div className="App">
{links.map((url) => (
<ReactPlayer key={url} playing={playing} onReady={onReady} url={url} />
))}
</div>
);
}
I also have created a codesandbox for you: https://codesandbox.io/s/kind-bardeen-59t8f?file=/src/App.js

Modify h1 inside a tsx file using a javascript function in js file

I need to generate random prompts inside of a H1 element in my tsx file. I have looked for solutions regarding this and all of them point to doing this in my index.html file, but I do not have one of those and I don't think I need one for the app I am making.
Here is the code I have,
Javascript file:
export function NewPrompt() {
var prompts = [
"one",
"2",
"three"
]
var randomNumber = Math.floor(Math.random() * prompts.Length);
var theText = document.getElementById('PromptDisplay').innerHTML;
return(
theText = randomNumber
);
}
here is the tsx file:
import React, { useState } from 'react';
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonCardHeader, IonCard, IonCardContent } from '#ionic/react';
import './RandomPrompts';
import './Tab2.css';
import AddItem from '../AddItem';
import ItemList from '../ItemList';
import { mic } from 'ionicons/icons';
import { NewPrompt } from './RandomPrompts';
import { analytics } from 'firebase';
const Tab2: React.FC = () => {
const [current, setCurrent] = useState(null);
const getEmpty = () => {
return ({
title: '',
content: '',
date: '',
location:'',
clear: '',
initialValue: ''
});
}
var random = require('./RandomPrompts.js');
const GetRandPrompt = () => {
return ({
random: NewPrompt()
})
}
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Writer's Unblock</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>
<IonCard>
<IonCardHeader>
<div id="PromptHolder">
<h1>Prompt: </h1>
<h2 id="PromptDisplay" onLoad={GetRandPrompt}></h2>
</div>
<br />
<h3>New Entry:</h3>
<AddItem title={current} clear={() =>setCurrent(getEmpty())}/>
</IonCardHeader>
<IonCardContent>
</IonCardContent>
{}
</IonCard>
</IonContent>
</IonPage>
);
};
export default Tab2;
What am I doing wrong here? I get no errors. I am also 100% new to ionic and react, and as my professor has not told us how to do anything I fear I am on my own to ask you guys for help. Anything you can offer would be appreciated!!!
this is not the EXACT code, but it should send you in the right direction
https://reactjs.org/docs/hooks-state.html
https://reactjs.org/docs/hooks-effect.html
const [prompt, setPrompt] = useState("");
useEffects(()=>{
let prompts = ["one", "2", "three" ]
let randomNumber = Math.floor(Math.random() * prompts.Length);
setPrompt(prompts[randomNumber])
})
// in template
<h2 id="PromptDisplay">{prompt}</h2>
Looking your code, I see you have your NewPromt imported into tsk. Again you call it with require in var random and set NewPromt to it in getRandPromt. I don't know why you have used it. What I suggest is to import the new promt like this
import NewPromt from './RandomPromt.js'
and use it like
<h2 id='PromtDisplay'><NewPromt/></h2>
Check the actual file names and spellings. On cellular device, sorry.
I fixed this. Trick was to put it in my AddItem file that adds the items to the data base.

Categories

Resources