Запретить повторный рендеринг внутри карты React

Я пытаюсь сделать клон netflix, когда я нахожу указатель мыши на изображение фильма, появляется трейлер этого фильма, возникает проблема, когда я наводю курсор мыши, у меня много одинаковых выходов в консоли. Я думаю, что эта проблема связана с тем, что я рендеринг внутри карты, но я ищу избежать этого для производительности... Я пробовал с React.memo, но не работает.

Вот пример

У меня есть родительский компонент

function MovieList(props) {
...
    <Movies movies={netflixMovies} title="Movie Feature" />
}

Внутри дочернего компонента у меня есть следующие

function Movie(props) {
...
const showMiniVideo = (id) => {
    setTimeout(() => {
      fetchYoutubeVideo(id) // Function who give me the ID of youtube video
        .then(res => {
          if (res.results.length === 0) { // If doesn't exist a video i set existVideo false
            setExistVideo(false)
            return setIdYoutubeVideo() // IdYoutubeVideo none
          }
          else {
            setExistVideo(true) // If exist a video i set existVideo true
            res.results.map(thriler => {
              return setIdYoutubeVideo(thriler.key) // IdYoutubeVideo id
            })
          }
        })
        .catch(err => {
          setExistVideo(false)
          console.error(err)
          return setIdYoutubeVideo()
        });
    }, 1000);
  }

...

return (
{movies.map(movie => (
              <div key={movie.id} className="tile">
                  <div onMouseOver={() => showMiniVideo(movie.id)} onMouseOut={stopMiniVideo}>
                    {idYoutubeVideo ?
                      (idMovie === movie.id ?
                        (existVideo ?
                          console.log("hay video")
                          :
                          console.log("no hay video")
                        )
                        :
                        console.log("no es el id")
                      )
                      :
                      <svg style={{ color: 'white' }} width="1.5vw" height="1.5vw" viewBox="0 0 16 16" className="bi bi-play-fill" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
                        <path d="M11.596 8.697l-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 0 1 0 1.393z" />
                      </svg>
                    }
                  </div>
                </div>
              </div>
            ))}
)}

У кого-нибудь есть идея? Буду признателен за любую помощь

3 ответа

Каждый раз, когда вы наводите указатель мыши на выполнение showMiniVideo(), выборка и установка состояния будут вызывать повторную визуализацию. старайтесь поддерживать флаг при наведении курсора мыши.

Но я бы сказал, что минимальное количество console.log = длина массива (фильмов), что нормально.

если больше, используйте флаг вроде этого -

if(isMouseOver) return;

return (
{movies.map(movie => (
              <div key={movie.id} className="tile">
                  <div onMouseOver={() => showMiniVideo(movie.id)} onMouseOut={stopMiniVideo}>
                    {idYoutubeVideo ?
                      (idMovie === movie.id ?
                        (existVideo ?
                          console.log("hay video")
                          :
                          console.log("no hay video")
                        )
                        :
                        console.log("no es el id")
                      )
                      :
                      <svg style={{ color: 'white' }} width="1.5vw" height="1.5vw" viewBox="0 0 16 16" className="bi bi-play-fill" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
                        <path d="M11.596 8.697l-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 0 1 0 1.393z" />
                      </svg>
                    }
                  </div>
                </div>
              </div>
            ))}
)}

isMouseOver должно быть ложным, только если все состояния обновляются при выполнении showMiniVideo(), например - setExistVideo,setIdYoutubeVideo...

Чао, да, ты прав: с React onMouseOverне имеет того же поведения, что и в обычном HTML. В HTML срабатывает только один раз. In React наверняка сработает, когда вы впервые войдете в объект, а затем неопределенное количество раз (иногда только когда вы выходите из объекта, иногда больше). Странный!

Чтобы решить эту проблему, вы можете использовать debounceфункции, которые предотвращают такое поведение. Вот пример, объясняющий, как использоватьdebounce.

В любом случае, спасибо, вы указали на то, чего я не знал!

Я думаю, что проблема в том, что вы не понимаете слушателя javascript. mouseoverсам. Mouseover вызывается (в значительной степени) каждый раз, когда вы наводите указатель мыши на элемент, который слушаете. Вы, вероятно, хотитеmouseenter а также mouseleave которые оба существуют в реакции как onMouseEnter а также onMouseLeave. Основное отличие здесь в том, что оба они срабатывают только один раз, когда указатель входит в область элемента или, соответственно, покидает ее.

Кстати, MDN фактически объясняет такое поведение в статье о наведении курсора мыши.

Не стесняйтесь возвращаться ко мне в комментариях, и удачного кодирования =)

Другие вопросы по тегам