Reactjs 为什么我在这个组件中得到额外的重新渲染?

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

为什么我在这个组件中得到额外的重新渲染?我就是不知道为什么?此问题是由组件内部引起的,而不是由父级引起的。每次状态更改时,它都会在控制台“内部预览容器”中显示两次 我甚至在
useffect()
中使用了
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);
import React,{useffect,useState}来自“React”;
导入“/PreviewContainer.scss”;
从“axios”导入axios;
从“react router dom”导入{withRouter};
功能预览容器(道具){
console.log(“内部预览容器”);
const[files,setFiles]=useState({image:,video:,name:,render:false,hideImage:true});
const[muted,setMuted]=useState(true);
让历史=道具。历史;
让insideMovie=props.insideMovie;
让formData=props.formData;
useffect(()=>{
控制台日志(“内部使用效果”);
axios.post(“http://localhost/netflix/index.php,formData)。然后((响应)=>{
if(response.data){
让电影;
如果(insideMovie){
movie=JSON.parse(response.data.movie);
}else movie=response.data;
设置文件({
希德迈格:是的,
image:movie.image.split(“/”[2],
视频:movie.video.split(“/”[2],
姓名:movie.name,
呈现:对,
});
}否则{
历史推送(“/404”);
}
});
},[formData,insideMovie,history]);
常量muteToggle=()=>{
设置静音(!静音);
};
常量showImage=()=>{
setFiles({…files,hideImage:false});
};
返回(
{files.render(
):null}
{files.name}
玩
{静音?:}
);
}
使用路由器导出默认值(PreviewContainer);

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

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

然后,如果您在组件中记录了一些内容,它将被记录下来,然后调用您的效果,从而产生两个日志。基于这一全面的分析,React将呈现您的组件,然后调用
useffect()
。这就是为什么不建议直接在React组件主体中记录某些内容(改为使用函数)。

useffect
将在依赖项数组中的变量每次更改时激发(在您的情况下,
formData
insideMovie
history
。如果希望它触发一次,只需将依赖项数组保留为空
[]
@DavidBuzatu问题没有解决,因为useEffect中的代码只执行一次anyway@DavidBuzatu我的意思是即使我离开额外的重新渲染仍在进行中。你确定每次更改状态时都会发生,而不仅仅是第一次吗?@Tarukami我想是的,因为在我更改静音状态的按钮上,只会导致双重重新渲染。如果我从数组中删除依赖项,我会收到此警告:React Hook Useffect缺少Dependent Cies:'formData'、'history'和'insideMovie'。包括它们或删除依赖项数组。这是第一次,它应该显示2 console.log(),但每次状态更改时,即使useEffect不再执行2 console.log()再次显示时,我认为这与useEffect无关,因为第一次执行useEffect内的console.log(),但其他时候只有useEffect()外的console.log()执行两次,而useEffect内的console.log()没有执行两次。即使我忽略警告并只留下[],它仍然显示console.log()每次状态更改两次。这是关于
useffect
和空的依赖项。我猜它会触发两次,因为:1.每次渲染时,您都会记录消息。2.当您开始渲染时,您在
showImage
中设置状态,然后再次触发重新渲染=>2个日志。即使我只更改了静音,总共有6个控制台日志state it display 2 console.logs()