Pull to refresh

Comments 10

Лучше сделать передачу не api, а ref, а методы в ref добавить через useImperativeHandle

Спасибо! Дополнил. Хотя, преимущество использовать ref для этого не совсем понятно. Разве что то, что ref-ы документация React считает "окном" в императивную работу с DOM.

Название ref устоявшееся, традиционное. А useImperativeHandle дополнительно может работать с рефом в виде функции, и обнуляет его при размонтировании (заодно отметим, он работает на том же этапе, что и useLayoutEffect, т.е. не будет сюрприза, если мы сами вдруг захотим использовать api в useLayoutEffect).

Нет требования, чтобы в useImperativeHandle закидывать именно реф, который пришел из forwardRef - подойдет любой реф.

А еще, плеер можно завернуть в нативный Custom Element и сильно упростить себе жизнь, опираясь на нативные колбеки жизненного цикла, которые браузер вызовет сам, при необходимости. Но осторожнее с этим, есть риск перестать быть "реакт-разработчиком" и познать дзен.

А можно не рисковать и использовать Custom Element оставаясь "реакт-разработчиком" https://legacy.reactjs.org/docs/web-components.html. А при необходимости, можно прокинуть нужные связки с внешним реакт, например router, для ссылок, которые должны оставаться в рамках SPA, а не перезагружать всю страницу.

спасибо за статью!

кажется один кейс тут упущен. если родительский компонент, например, хочет чтобы видео всегда проигрывалось (не реагировало на внутренние кнопки стоп), то это следует написать так

    <VideoPlayer
      source={SOURCES_MOCK}
      status="playing"
      onStatusChange={() => {}}
    />

но это просто не сработает

Работать будет. Но вы правы в том плане, что когда видео доиграет до конца, оно не начнёт проигрываться заново. Для этого более тонкая логика нужна в VideoPlayer.

точно всё сработает? может, конечно, я не всё в голове удержал. но тогда укажите где я ошибся.

  1. пользователь нажал на внутреннюю кнопку паузы (или пробел, не важно)

  2. плеер встанет в паузу

  3. отработает колбек этой подписки player.current.addListener("statusChange", props.onStatusChange);

  4. props.onStatusChange передаётся пустой (или вовсе не передаётся). соответсвенно в родителе ничего не меняется и в props.status всё ещё лежит "playing"

и того имеем props.status === "playing" а плеер на паузе

этот useEffect(() => {...}, [props.status]); не сработает, потому что props.status не поменялся

Теперь понятно, какой кейс вы имеете ввиду. Да, в статье не обрабатывается такой случай. Доработаю, спасибо.

Я подумал над этой проблемой. Я хочу оставить её решение за рамками этой статьи.

Начальная задача была сделать из императивного компонента декларативный. И сейчас компонент работает аналогично декларативным нативным компонентам, таким как, например, <input />. У них если не контролировать onChange в родителе, то также value будет присваиваться только при ре-рендеринге родителя.

Это не совсем соответствует идеальной декларативности. Но до идеала, наверное, и не добраться, т.к., например, если пользователь нажал внутри плеера stop, а мы программно заставим его вернуться на то же место и играть дальше, то видео всё равно успеет "дёрнуться". Поэтому, я думаю, здесь уже надо отталкиваться от бизнес-задач и конкретной реализации плеера.

Если я на практике столкнусь с тем, чтобы нужно было в нашей обёртке контролировать бизнес-логику, то, может быть, напишу продолжение.

Sign up to leave a comment.

Articles