【问题标题】:Prevent Re-rendering inside a map React防止在地图内重新渲染 React
【发布时间】:2020-07-29 20:40:59
【问题描述】:

我正在尝试克隆 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>
            ))}
)}

有人有想法吗?我会很感激任何帮助

【问题讨论】:

    标签: reactjs react-hooks react-memo


    【解决方案1】:

    我认为您遇到的问题是不了解 javascript 侦听器 mouseover 本身。每次将鼠标移到正在收听的元素上时,都会调用 Mouseover get(几乎)。你可能想要的是mouseenter 和mouseleave,它们都以onMouseEnter 和onMouseLeave 的形式存在。这里的主要区别是它们都只触发一次,一旦指针进入元素区域,或者分别离开它。

    顺便说一句,MDN 实际上在 article about mouseover 中解释了这种行为。

    请随时在 cmets 中回复我,祝您编码愉快 =)

    【讨论】:

      【解决方案2】:

      每次您将鼠标悬停在执行的 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>
                  ))}
      )}
      

      只有在执行 showMiniVideo() 时所有状态都更新时,isMouseOver 才应该为 false,例如 - setExistVideo,setIdYoutubeVideo...

      【讨论】:

        【解决方案3】:

        Ciao,是的,你是对的:React onMouseOver 的行为与普通 HTML 不同。在 HTML 中只会触发一次。在 React 中,当您第一次进入对象时肯定会触发,然后是不确定的次数(有时仅在您离开对象时,有时更多)。奇怪!

        要解决这个问题,您可以使用debounce 函数来防止这种行为。 Here 一个例子说明如何使用debounce。

        无论如何谢谢,你指出了一些我不知道的事情!

        【讨论】:

          猜你喜欢
          • 2021-05-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-08-12
          • 1970-01-01
          • 2021-09-10
          • 2021-02-14
          • 1970-01-01
          相关资源
          最近更新 更多