【问题标题】:Does not exist on type 'false | HTMLAudioElement'不存在于类型 'false | HTMLAudioElement'
【发布时间】:2022-01-23 23:05:14
【问题描述】:

在带有使用 typescript 的钩子的 React (Next.js) 中,我想创建对音频的引用。我得到的错误是:-

Property 'duration' does not exist on type 'false | HTMLAudioElement'.
  Property 'duration' does not exist on type 'false'.ts(2339)
const audioRef = useRef(typeof Audio !== 'undefined' && new Audio(mp3Src));
  const { duration } = audioRef.current.duration;

我也试过这样

  const audioRef = useRef(new Audio(mp3Src));
  const { duration } = audioRef.current;

然后在浏览器中引发错误

Server Error
ReferenceError: Audio is not defined

This error happened while generating the page. Any console logs will be displayed in the terminal window.

完整代码

import type { NextPage } from 'next';
import React, { useRef, useState } from 'react';
import Image from 'next/image';

interface Props {
  imgSrc: string;
  mp3Src: string;
}

const AudioPlayer: NextPage<Props> = ({ imgSrc, mp3Src }) => {
  // const audioRef = useRef(new Audio(mp3Src));
  const audioRef = useRef(typeof Audio !== 'undefined' && new Audio(mp3Src));

  // const duration = audioRef.current.duration;
  const { duration } = audioRef.current;

  const intervalRef = useRef<any>();
  const [trackProgress, setTrackProgress] = useState<number>(0);
  const [isPlaying, setIsPlaying] = useState<boolean>(false);

  const play = (): void => {
    audioRef.current.play();
    startTimer();
    setIsPlaying(true);
  };

  const pause = (): void => {
    audioRef.current.pause();
    setIsPlaying(false);
  };

  const startTimer = (): void => {
    clearInterval(intervalRef.current);
    intervalRef.current = setInterval(() => {
      setTrackProgress(audioRef.current.currentTime);
    }, 100);
  };

  const onScrub = (value: number): void => {
    // Clear any timers already running
    clearInterval(intervalRef.current);
    audioRef.current.currentTime = value;
    setTrackProgress(audioRef.current.currentTime);
  };

  const onScrubEnd = (): void => {
    if (!isPlaying) {
      setIsPlaying(true);
    }
    startTimer();
  };
  const mute = (): void => {
    audioRef.current.volume = 0;
  };
  return (
    <div className='AudioPlayer'>
      <Image alt='menu' src={imgSrc} width='30' height='20' />
      <div onClick={play}>Play</div>
      <div onClick={pause}>Pause</div>
      <div>{trackProgress}</div>
      <div>{isPlaying}</div>
      <input
        type='range'
        value={trackProgress}
        step='1'
        min='0'
        max={duration ? duration : `${duration}`}
        className='progress'
        onChange={(e): void => onScrub(+e.target.value)}
        onMouseUp={onScrubEnd}
        onKeyUp={onScrubEnd}
      />
      <div onClick={mute}>Mute</div>
    </div>
  );
};

export default AudioPlayer;

【问题讨论】:

  • 如果audioRef.current 为假,你想做什么?或者等效地,如果 Audio 未定义,你想做什么?
  • 如果audioRef.current 为假,我可以记录源无效,如果Audio 未定义,我可以记录浏览器不支持音频
  • K,那么您只需要在代码中检查这种情况。有关检查 audioRef.current 是否为假的示例,请参阅 Saravana 的答案。

标签: reactjs typescript next.js


【解决方案1】:

NextJS 使用 Node 渲染服务器中的任何内容,允许您构建静态和服务器端渲染的应用程序。因此,Node 中不存在任何浏览器的 API,例如 window 或在您的情况下为 Audio

当 Next 尝试在节点上运行以下代码时,并且由于 Audio 不存在。它将评估为false,因为typeof Audioundefined

const audioRef = useRef(typeof Audio !== 'undefined' && new Audio(mp3Src));

为确保代码仅在浏览器(而非 Node)上运行,您可以使用 useEffect 挂钩。

例如

const AudioPlayer: NextPage<Props> = ({ imgSrc, mp3Src }) => {
  // const audioRef = useRef(new Audio(mp3Src));
  const [audioElem, setAudioElem] = useState<HTMLAudioElement>();

  useEffect(() => {
    if (typeof Audio !== 'undefined' && mp3Src) {
      const audio = new Audio(mp3Src);
      setAudioElem(audio);
    }
  }, [mp3Src])
  

  // const duration = audioRef.current.duration;
  const { duration } = audioElem || {};

...

一些有用的链接;

【讨论】:

  • 知道了,谢谢
猜你喜欢
  • 2020-03-05
  • 2010-12-04
  • 2020-10-16
  • 2018-07-09
  • 1970-01-01
  • 2011-04-02
  • 1970-01-01
  • 2022-01-10
  • 1970-01-01
相关资源
最近更新 更多