更新组件而不在React中重新渲染它

问题描述 投票:0回答:1

我正在 React 中制作简单的音频可视化器。在组件中,我添加了 vizualizeData 函数和handleAudio 函数。我想创建一个功能,以便用户可以更改画布上创建的条形的颜色和宽度。我导入了滑块并创建了 onChangeEvenetTrigered 函数。当我激活它时,条形的宽度会发生变化,但我的可视化会暂停一会儿,我认为组件会重新渲染自身?我该怎么办?

这是我的组件中的代码。

`import { useRef, useState } from "react";

import Slider from 'rc-slider';
import 'rc-slider/assets/index.css';


let animationController;

export default function Bars() {
  const [file, setFile] = useState(null);
  const canvasRef = useRef();
  const audioRef = useRef();
  const source = useRef();
  const analyzer = useRef();
  const [sliderValue, setSliderValue] = useState(23)

  //slider

  const OnChangeEventTriggerd = (newValue) => {
    console.log("new Value", newValue);
    setSliderValue(newValue);
  };



  const handleAudioPlay = () => {
    let audioContext = new AudioContext();
    if (!source.current) {
      source.current = audioContext.createMediaElementSource(audioRef.current);
      analyzer.current = audioContext.createAnalyser();
      source.current.connect(analyzer.current);
      analyzer.current.connect(audioContext.destination);
      console.log(analyzer.current, source.current, analyzer.current )
    }
    visualizeData();
  };
  
  const visualizeData = () => {
    animationController = window.requestAnimationFrame(visualizeData);
    if (audioRef.current.paused) {
      return cancelAnimationFrame(animationController);
    }
    const songData = new Uint8Array(140);
    analyzer.current.getByteFrequencyData(songData);
   
    const bar_width = sliderValue;
    let start = 0;
    const ctx = canvasRef.current.getContext("2d");
    ctx.clearRect(0, 0, canvasRef.current.width, canvasRef.current.height);
    for (let i = 0; i < songData.length; i++) {
      // compute x coordinate where we would draw
      start = i * 8;
      //create a gradient for the  whole canvas
      let gradient = ctx.createLinearGradient(
        0,
        0,
        canvasRef.current.width,
        canvasRef.current.height
      );
      gradient.addColorStop(0.2, "green");
      gradient.addColorStop(0.5, "blue");
      gradient.addColorStop(0.4, "red");

  
    ctx.fillStyle = gradient;
    ctx.fillRect(start, canvasRef.current.height, bar_width, -songData[i]);
     ctx.strokeRect(start, canvasRef.current.height, bar_width, -songData[i]);
      
    }
  };

  return (
    <div className="App">
      <div className="border border-red-700 max-w-container mx-auto flex flex-col">
      <div className="border border-black order-last flex">
      <input
        type="file"
        onChange={({ target: { files } }) => files[0] && setFile(files[0])}
      />
      {file && (
        <audio
          ref={audioRef}
          onPlay={handleAudioPlay}
          src={window.URL.createObjectURL(file)}
          controls
        />
      )}

    <div className="w-[250px]">
      <Slider
      defaultValue={sliderValue}
      min={3}
      max={300}
      onChange={OnChangeEventTriggerd}
       
         />
     </div>

      </div>  
      
      <canvas ref={canvasRef} width={700} height={420}  className="mx-auto border border-red-700"/>
      </div>


    
        
    </div>
  );
} `;

我尝试使用 useMemo Hook 但没有走得太远。

reactjs react-hooks rerender
1个回答
0
投票

欢迎来到社区!是的,就我而言,这是由于重新渲染而发生的。为了解决这个问题,您可以简单地使用 useMemo/useCallback 钩子来缓存独立于某个事件的状态。

查看此问题以获取有关上述挂钩使用情况的更多信息:https://stackoverflow.com/a/66590428/14953535

© www.soinside.com 2019 - 2024. All rights reserved.