微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 React 中转换为函数式组件时面临的问题

如何解决在 React 中转换为函数式组件时面临的问题

这是一个非常小的两页项目,因此不会花费太多时间。

我正在尝试将 this Github 存储库从基于类的组件转换为功能组件。我非常接近,但逻辑无法正常工作。 尤其是 useState 钩子,因为值没有被保存。所以我尝试了不同的方法

这是原始项目的现场演示的预期输出

https://matt-eric.github.io/web-audio-fft-visualization-with-react-hooks/

这就是我所在的地方。 This is the sandbox link

暂时忽略 The error you provided does not contain a stack trace. 错误。单击 x 并刷新小 project window(不是您的浏览器选项卡)几次,直到音频在刷新时播放。这是因为谷歌阻止您在加载时播放音乐。

我想通过单击按钮而不是加载来播放音频。但它不起作用。

感谢任何调查它的人。

解决方法

需要一些清理工作,但这是有效的。 https://codesandbox.io/s/xenodochial-wildflower-c5b35

我真正做的就是将所有函数放在 useCallback 中,使 audioFile 成为参考,然后使 toggleAudio 函数根据当前状态播放或暂停音频.我看到的最大问题之一是您试图在单击时初始化音频,但这确实应该在安装时完成,然后当您单击时音频才开始。此外,如果您在每次点击时都进行初始化,则会导致错误,因为它已经初始化。

如果您有任何问题,请告诉我!

,

使用您的沙箱,我发现缺少一些东西:

  1. 你需要记住你的 audoFile(因为你创建了一个新的音频并且它永远不会改变)

  2. 你的函数需要稳定,因此需要是react hook函数,特别是useCallback函数。

  3. 在演示中的 onClick 函数(开始按钮)中,您调用了 initalizeAudioAnalyzer ,但该函数已经使用您在 functionCont.jsx 上的 useEffect 进行了初始化,不需要再次初始化。一旦我删除了它,一切都奏效了。

这是现在播放音频的修复代码:

functionCont.jsx:

import React,{ useCallback,useEffect,useMemo,useState } from "react";
import VisualDemo from "./functionViz";
// import VisualDemo from "./VisualDemo";
import soundFile from "../audio/water.mp3";

const FunctionCont = () => {
  const audioFile = useMemo(() => {
    const audio = new Audio();
    audio.crossOrigin = "anonymous";
    return audio;
  },[]);

  const [audioData,setAudioData] = useState();
  let frequencyBandArray = [...Array(25).keys()];

  const initializeAudioAnalyser = useCallback(() => {
    const audioContext = new AudioContext();
    const source = audioContext.createMediaElementSource(audioFile);
    const analyser = audioContext.createAnalyser();
    audioFile.src = soundFile;
    
    analyser.fftSize = 64;

    source.connect(audioContext.destination);
    source.connect(analyser);

    setAudioData(analyser);
    audioFile.play();
  },[audioFile]);

  useEffect(() => {
    initializeAudioAnalyser();
  },[initializeAudioAnalyser]);

  const getFrequencyData = useCallback((styleAdjuster) => {
    const bufferLength = audioData.frequencyBinCount;
    const amplitudeArray = new Uint8Array(bufferLength);
    audioData.getByteFrequencyData(amplitudeArray);
    styleAdjuster(amplitudeArray);
  },[audioData]);

  return (
    <div>
      <VisualDemo
        frequencyBandArray={frequencyBandArray}
        getFrequencyData={getFrequencyData}
        // audioData={audioData}
        audioFile={audioFile}
      />
    </div>
  );
};

export default FunctionCont;

functionViz.jsx

import React,{ useRef,useState } from "react";
import Paper from "@material-ui/core/Paper";
import IconButton from "@material-ui/core/IconButton";
import Tooltip from "@material-ui/core/Tooltip";
import EqualizerIcon from "@material-ui/icons/Equalizer";
import { makeStyles } from "@material-ui/core/styles";
import "../stylesheets/App.scss";

const useStyles = makeStyles((theme) => ({
  flexContainer: {
    display: "flex",flexWrap: "wrap",justifyContent: "center",paddingTop: "25%"
  }
}));

const VisualDemo = (props) => {
  const classes = useStyles();

  const amplitudeValues = useRef(null);

  function adjustFreqBandStyle(newAmplitudeData) {
    amplitudeValues.current = newAmplitudeData;
    let domElements = props.frequencyBandArray.map((num) =>
      document.getElementById(num)
    );
    for (let i = 0; i < props.frequencyBandArray.length; i++) {
      let num = props.frequencyBandArray[i];
      domElements[
        num
      ].style.backgroundColor = `rgb(0,255,${amplitudeValues.current[num]})`;
      domElements[num].style.height = `${amplitudeValues.current[num]}px`;
    }
  }

  function runSpectrum() {
    props.getFrequencyData(adjustFreqBandStyle);
    requestAnimationFrame(runSpectrum);
  }

  function handleStartButtonClick() {
    requestAnimationFrame(runSpectrum);
  }

  return (
    <div>
      <div>
        <Tooltip title="Start" aria-label="Start" placement="right">
          <IconButton
            id="startButton"
            onClick={handleStartButtonClick}
            // disabled={!!props.audioData ? true : false}
          >
            <EqualizerIcon />
          </IconButton>
        </Tooltip>
      </div>

      <div className={classes.flexContainer}>
        {props.frequencyBandArray.map((num) => (
          <Paper
            className={"frequencyBands"}
            elevation={4}
            id={num}
            key={num}
          />
        ))}
      </div>
    </div>
  );
};
export default VisualDemo;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?