在reactjs中播放声音

Daw*_*n17 11 javascript reactjs

import React, { Component } from 'react'
import { Button, Input, Icon,Dropdown,Card} from 'semantic-ui-react'
import { Link } from 'react-router-dom'
import $ from 'jquery'
import styles from './Home.scss'
import Modal from './Modal.jsx'
import MakeChannelModal from './MakeChannelModal.jsx'

class Music extends React.Component {
    constructor(props) {
    super(props);
    this.state = {

      play: false,
      pause: true

    };

    this.url = "http://streaming.tdiradio.com:8000/house.mp3";
    this.audio = new Audio(this.url);

  }

  play(){
    this.setState({
      play: true,
      pause: false
    });
    console.log(this.audio);
    this.audio.play();
  }

  pause(){
  this.setState({ play: false, pause: true });
    this.audio.pause();
  }

  render() {

  return (
    <div>
      <button onClick={this.play}>Play</button>
      <button onClick={this.pause}>Pause</button>
    </div>
    );
  }
}


export default Music
Run Code Online (Sandbox Code Playgroud)

这是我用来在我的反应应用程序中使用url(this.url)播放声音的代码.当我按下播放按钮时,它会给我一个错误

Uncaught TypeError: Cannot read property 'setState' of undefined

我不确定为什么这是开心的,因为我没有看到任何未定义的状态.一个;; 国家已经宣布.

我是新手,所以我可能会遗漏一些非常重要的东西.

请帮忙!

Jax*_*axx 29

您需要绑定都eventListenereventListener你的构造方法,以便eventListener使用中的任一方法指的是组件的实例.

在退出构造函数之前添加这两行:

class Music extends React.Component {
  state = {
    play: false
  }
  audio = new Audio(this.props.url)

  componentDidMount() {
    audio.addEventListener('ended', () => this.setState({ play: false }));
  }

  componentWillUnmount() {
    audio.removeEventListener('ended', () => this.setState({ play: false }));  
  }

  togglePlay = () => {
    this.setState({ play: !this.state.play }, () => {
      this.state.play ? this.audio.play() : this.audio.pause();
    });
  }

  render() {
    return (
      <div>
        <button onClick={this.togglePlay}>{this.state.play ? 'Pause' : 'Play'}</button>
      </div>
    );
  }
}

export default Music;
Run Code Online (Sandbox Code Playgroud)

此外,但这不是你的问题,你可以真正缩短你的代码,那里有很多冗余.就像是:

编辑:更新为使用ES6类属性语法

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

const useAudio = url => {
  const [audio] = useState(new Audio(url));
  const [playing, setPlaying] = useState(false);

  const toggle = () => setPlaying(!playing);

  useEffect(() => {
      playing ? audio.play() : audio.pause();
    },
    [playing]
  );

  useEffect(() => {
    audio.addEventListener('ended', () => setPlaying(false));
    return () => {
      audio.removeEventListener('ended', () => setPlaying(false));
    };
  }, []);

  return [playing, toggle];
};

const Player = ({ url }) => {
  const [playing, toggle] = useAudio(url);

  return (
    <div>
      <button onClick={toggle}>{playing ? "Pause" : "Play"}</button>
    </div>
  );
};

export default Player;
Run Code Online (Sandbox Code Playgroud)

Hooks版本(React 16.8+):

class Music extends React.Component {
  state = {
    play: false
  }
  audio = new Audio(this.props.url)

  componentDidMount() {
    audio.addEventListener('ended', () => this.setState({ play: false }));
  }

  componentWillUnmount() {
    audio.removeEventListener('ended', () => this.setState({ play: false }));  
  }

  togglePlay = () => {
    this.setState({ play: !this.state.play }, () => {
      this.state.play ? this.audio.play() : this.audio.pause();
    });
  }

  render() {
    return (
      <div>
        <button onClick={this.togglePlay}>{this.state.play ? 'Pause' : 'Play'}</button>
      </div>
    );
  }
}

export default Music;
Run Code Online (Sandbox Code Playgroud)


Gas*_*ass 15

您还可以使用useSound钩子来完成此操作。

为此,首先安装 npm 包:

npm install use-sound
Run Code Online (Sandbox Code Playgroud)

进口:

import useSound from 'use-sound'
import mySound from '../assets/sounds/yourSound.mp3' // Your sound file path here
Run Code Online (Sandbox Code Playgroud)

使用示例1

一个简单的方法..

function MyButton(){
  const [playSound] = useSound(mySound)
  
  return (
    <button onClick={() => playSound()}>
       Play Sound
    </button>
  )
}
Run Code Online (Sandbox Code Playgroud)

使用示例2

在此设置中我们可以控制音量。此外,playSound()将在handleClick()函数内部调用,使您可以通过单击执行更多操作,而不仅仅是播放声音。

function MyButton(){
  const [playSound] = useSound(mySound, { volume: 0.7 }) // 70% of the original volume
  
  const handleClick = () => {
    playSound()
    // maybe you want to add other things here?
  }

  return (
    <button onClick={() => handleClick()}>
       Play Sound
    </button>
  )
}
Run Code Online (Sandbox Code Playgroud)

欲了解更多信息,请点击此处此处

  • 非常干净的解决方案!对于打字稿,刚刚添加了一个带有“声明模块“*.mp3”的 .d.ts 文件;声明模块“*.wav”;`正如此处指出的:/sf/answers/5112607811/并且工作起来就像一个魅力 (2认同)

小智 6

我在执行答案时遇到了不同的问题。

浏览器似乎在每次重新渲染时不断尝试下载声音。

我最终使用了useMemo没有依赖项的音频,这导致挂钩只创建一次音频并且从不尝试重新创建它。

import {useMemo, useEffect, useState} from "react";

const useAudio = url => {
    const audio = useMemo(() => new Audio(url), []);
    const [playing, setPlaying] = useState(false);

    const toggle = () => setPlaying(!playing);

    useEffect(() => {
            playing ? audio.play() : audio.pause();
        },
        [playing]
    );

    useEffect(() => {
        audio.addEventListener('ended', () => setPlaying(false));
        return () => {
            audio.removeEventListener('ended', () => setPlaying(false));
        };
    }, []);

    return [playing, toggle];
};

export default useAudio;

Run Code Online (Sandbox Code Playgroud)