【问题标题】:Why am I getting extra re-renders in this component?为什么我会在此组件中获得额外的重新渲染?
【发布时间】:2020-08-04 21:17:08
【问题描述】:

为什么我在这个组件中得到了额外的重新渲染,我就是不知道为什么?此问题是在组件内部引起的,而不是由父级引起的。每次状态更改时,它都会在控制台“内部预览容器”中显示两次 我什至在useEffect() 中使用useRef() 将旧值与当前值进行比较,结果显示了两次 文件未定义然后文件{ image: "", video: "", name: "", render: false, hideImage: true }

   import React, { useEffect, useState } from "react";
    import "./PreviewContainer.scss";
    import axios from "axios";
    import { withRouter } from "react-router-dom";
    function PreviewContainer(props) {
      console.log("Inside Preview Container");
      const [files, setFiles] = useState({ image: "", video: "", name: "", render: false, hideImage: true });
      const [muted, setMuted] = useState(true);
      let history = props.history;
      let insideMovie = props.insideMovie;
      let formData = props.formData;
      useEffect(() => {
        console.log("inside useEffect");
        axios.post("http://localhost/netflix/index.php", formData).then((response) => {
          if (response.data) {
            let movie;
            if (insideMovie) {
              movie = JSON.parse(response.data.movie);
            } else movie = response.data;
            setFiles({
              hideImage: true,
              image: movie.image.split("/")[2],
              video: movie.video.split("/")[2],
              name: movie.name,
              render: true,
            });
          } else {
            history.push("/404");
          }
        });
      }, [formData, insideMovie, history]);
    
      const muteToggle = () => {
        setMuted(!muted);
      };
      const showImage = () => {
        setFiles({ ...files, hideImage: false });
      };
      return (
        <div className="preview-container">
          {files.render ? (
            <>
              <img
                className="preview-image"
                alt={files.name}
                src={require(`../../assets/entities/thumbnails/${files.image}`)}
                hidden={files.hideImage}
              ></img>
    
              <video onEnded={showImage} className="preview-video" muted={muted} autoPlay hidden={!files.hideImage}>
                <source src={require(`../../assets/entities/previews/${files.video}`)} type="video/mp4"></source>
              </video>
            </>
          ) : null}
    
          <div className="preview-overlay">
            <div className="mainDetails">
              <h3>{files.name}</h3>
    
              <div className="video-controls">
                <button>
                  <i className="fas fa-play"></i> Play
                </button>
                <button onClick={muteToggle}>{muted ? <i className="fas fa-volume-mute"></i> : <i className="fas fa-volume-up"></i>}</button>
              </div>
            </div>
          </div>
        </div>
      );
    }
    
    export default withRouter(PreviewContainer);

【问题讨论】:

  • useEffect 将触发 每次 依赖项数组中的变量更改(在您的情况下,formDatainsideMoviehistory。如果你想要它触发一次,只需将依赖数组留空[]
  • @DavidBuzatu 问题没有解决,顺便说一句 useEffect 里面的代码无论如何只执行一次
  • @DavidBuzatu 我的意思是即使我离开 [] 额外的重新渲染仍在发生
  • 您确定每次更改状态时都会发生这种情况,而不仅仅是第一次更改?
  • @Tarukami 我认为是的,因为在我更改静音状态的按钮上,它只会导致双重重新渲染

标签: reactjs


【解决方案1】:

首先,如果您希望您的useEffect 充当componentDidMount,这意味着您只需要一个渲染,您应该将依赖项数组留空:

useEffect(() => {
    //...work
}, []);

然后,如果您在组件中记录某些内容,它将被记录并然后调用您的效果,从而产生 2 个日志。基于这个综合的answer,React 会渲染你的组件,然后调用useEffect()。这就是为什么不建议直接在 React 组件主体中记录某些内容的原因(改用函数)。

【讨论】:

  • 如果我从数组中删除依赖项,我会收到此警告 React Hook useEffect 缺少依赖项:'formData'、'history' 和 'insideMovie'。要么包含它们,要么删除依赖数组。第一次是真的,它应该显示 2 console.log() 但是每次状态都改变了,即使 useEffect 没有再次执行 2 console.log() 再次显示,我认为这与 useEffect 无关因为第一次执行 useEffect 内部的 console.log() ,但其他时候只执行 useEffect() 外部的 console.log() 两次,而在 useEffect 内部则不执行。
  • 即使我忽略警告并只留下 [] 它仍然会在每次状态更改时显示 console.log() 两次。
  • 这是关于useEffect 和空依赖的docs。我猜它会触发两次,因为: 1. 在每次渲染时,您都会记录您的消息。 2. 当你开始渲染时,你在showImage 中设置状态,然后再次触发重新渲染 => 2 个日志。
  • 总共有 6 个 console.logs,即使我只更改它显示 2 个 console.logs() 的静音状态
猜你喜欢
  • 2020-05-06
  • 2020-10-15
  • 2011-09-22
  • 2021-05-11
  • 2021-05-11
  • 1970-01-01
  • 2021-10-23
  • 2020-03-02
  • 1970-01-01
相关资源
最近更新 更多