Переменная useRefs - начальное значение ссылки на div?

Я пытаюсь создать панель звуковой обработки с помощью хуков реакции. Я следил за учебником по компонентам на основе класса реакции, но немного заблудился с refs.

Как я могу присвоить моим переменным useRef начальное значение div ref при загрузке страницы?

Как только я начинаю играть, я получаю сообщение об ошибке, что не могу прочитать значение offsetwidth, равное нулю. Очевидно, что ссылка на шкалу времени имеет значение NULL, поскольку не имеет начального значения. Как я могу подключить его к div с идентификатором временной шкалы в хуке useEffect?

const AudioPlayer = () => {
  const url = "audio file";

  const [audio] = useState(new Audio(url));
  const [duration, setDuration] = useState(0);
  const [currentTime, setCurrentTime] = useState(0)
  let timelineRef = useRef()
  let handleRef = useRef()

  useEffect(() => {
    audio.addEventListener('timeupdate', e => {
      setDuration(e.target.duration);
      setCurrentTime(e.target.currentTime)
      let ratio = audio.currentTime / audio.duration;
      let position = timelineRef.offsetWidth * ratio;
      positionHandle(position);
    })
  }, [audio, setCurrentTime, setDuration]);



  const mouseMove = (e) => {
    positionHandle(e.pageX);
    audio.currentTime = (e.pageX / timelineRef.offsetWidth) * audio.duration;
  };

  const mouseDown = (e) => {
    window.addEventListener('mousemove', mouseMove);
    window.addEventListener('mouseup', mouseUp);
  };

  const mouseUp = (e) => {
    window.removeEventListener('mousemove', mouseMove);
    window.removeEventListener('mouseup', mouseUp);
  };

  const positionHandle = (position) => {
    let timelineWidth = timelineRef.offsetWidth - handleRef.offsetWidth;
    let handleLeft = position - timelineRef.offsetLeft;
    if (handleLeft >= 0 && handleLeft <= timelineWidth) {
      handleRef.style.marginLeft = handleLeft + "px";
    }
    if (handleLeft < 0) {
      handleRef.style.marginLeft = "0px";
    }
    if (handleLeft > timelineWidth) {
      handleRef.style.marginLeft = timelineWidth + "px";
    }
  };


  return (
    <div>

      <div id="timeline" ref={(timeline) => { timelineRef = timeline  }}>
      <div id="handle" onMouseDown={mouseDown} ref={(handle) => { handleRef = handle }} />
      </div>
    </div> 
  )
}

person user10045300    schedule 27.03.2020    source источник


Ответы (1)


Хук useRef() возвращает ссылку на объект со свойством current. Свойство current - это фактическое значение, на которое указывает useRef.

Чтобы использовать ссылку, просто установите ее на элемент:

<div id="timeline" ref={timelineRef}>
<div id="handle" onMouseDown={mouseDown} ref={handleRef} />

А затем, чтобы использовать его, вам нужно обратиться к свойству current:

let position = current.timelineRef.offsetWidth * ratio;

И positionHandle - на самом деле вам не следует таким образом устанавливать стили для элементов в React. Используйте ловушку setState() и установите стиль с помощью JSX.

const positionHandle = (position) => {
  let timelineWidth = timelineRef.current.offsetWidth - handleRef.current.offsetWidth;
  let handleLeft = position - timelineRef.current.offsetLeft;
  if (handleLeft >= 0 && handleLeft <= timelineWidth) {
      handleRef.current.style.marginLeft = handleLeft + "px";
  }
  if (handleLeft < 0) {
    handleRef.current.style.marginLeft = "0px";
  }
  if (handleLeft > timelineWidth) {
    handleRef.current.style.marginLeft = timelineWidth + "px";
  }
};

Кроме того, ссылка также может использоваться для других значений, таких как new Audio(url), и извлекаться из свойства current:

const { current: audio } = useRef(new Audio(url));
person Ori Drori    schedule 27.03.2020
comment
Спасибо, что сработало как шарм, хотя с let position = timelineRef.current.offsetWidth * ratio; - person user10045300; 27.03.2020