You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在JSX中使用map生成Audio组件时出现audioRef未定义问题

React中通过map生成

我尝试用map批量生成

import React, { useState, useRef, createRef } from 'react';

const audios = [{ src: '/fire.mp3' }, { src: '/crickets.mp3' }];

function Audio({ audioRef }) {
  const { src, ref } = audioRef;

  function handleVolumeChange(value) {
    ref.current.volume = value / 100;
  }

  return (
    <audio ref={ref} loop>
      <source src={src} type="audio/mpeg" /> Your browser does not support the
      audio element.
    </audio>
    // `handleVolumeChange` is used here
  );
}

export const App = ({ name }) => {
  const audioRefs = useRef(
    audios.map((audio) => ({
      ...audio,
      ref: createRef(),
    }))
  );
    
  return (
    <>
      {audioRefs.current.map((audioRef, index) => (
        <Audio key={audioRef.src} audio={audioRef} />
      ))}
    </>
  );
};

运行时出现错误:

Cannot destructure property 'src' of 'audioRef' as it is undefined.

明明audioRefs是包含两个对象的数组:

[{…}, {…}]
  0: Object
    ref: Object
    src: "/fire.mp3"
    <prototype>: Object
  1: Object
    ref: Object
    src: "/crickets.mp3"
    <prototype>: Object

需求:需要通过ref控制


问题原因

父组件给<Audio>传递的props属性名是audio,但子组件Audio声明接收的参数是audioRef,两者命名不匹配,导致子组件内的audioRef为undefined,无法解构出src和ref。

修复方案

1. 统一props命名

要么修改子组件的接收参数名,要么修改父组件的传递属性名,二选一即可:

方案A:修改子组件接收参数

function Audio({ audio }) {
  const { src, ref } = audio;
  // 其余逻辑保持不变
}

方案B:修改父组件传递的属性名

// 父组件中渲染Audio时修改属性名
<Audio key={audioRef.src} audioRef={audioRef} />

2. 补充音量控制实现示例

如果需要实现音量调节功能,可以在子组件中添加滑块控件,结合ref操作audio元素:

function Audio({ audio }) {
  const { src, ref } = audio;

  const handleVolumeChange = (e) => {
    const volumeValue = e.target.value / 100;
    if (ref.current) {
      ref.current.volume = volumeValue;
    }
  };

  return (
    <div className="audio-control">
      <audio ref={ref} loop>
        <source src={src} type="audio/mpeg" /> 
        Your browser does not support the audio element.
      </audio>
      <input 
        type="range" 
        min="0" 
        max="100" 
        defaultValue="50" 
        onChange={handleVolumeChange}
        title="调节音量"
      />
    </div>
  );
}

3. 优化ref初始化方式(可选)

也可以用useRef结合useEffect来初始化ref数组,逻辑更清晰:

export const App = ({ name }) => {
  const audioRefs = useRef([]);

  useEffect(() => {
    // 初始化每个audio对应的ref
    audioRefs.current = audios.map(() => createRef());
  }, []);
    
  return (
    <>
      {audios.map((audio, index) => (
        <Audio 
          key={audio.src} 
          audio={{
            src: audio.src,
            ref: audioRefs.current[index]
          }} 
        />
      ))}
    </>
  );
};

内容的提问来源于stack exchange,提问作者wyc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 06:42:49