Javascript 即使依赖关系数组对象在Reactjs中保持不变,也可以单击按钮重新呈现页面

Javascript 即使依赖关系数组对象在Reactjs中保持不变,也可以单击按钮重新呈现页面,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我使用的是React 17.0.1。我无法理解以下几点: 如果多次单击按钮,即使id保持不变,页面也会重新呈现 我还遇到了另一个错误:第25:6行:React Hook useEffect缺少依赖项:“id”。包括它或删除依赖项数组react hooks/dep。 我猜这个错误是由于id设置在渲染外部造成的 import React,{useState,useffect}来自“React”; 从“axios”导入axios; 函数datafetching(){ const[post,setPos

我使用的是React 17.0.1。我无法理解以下几点:

  • 如果多次单击按钮,即使id保持不变,页面也会重新呈现
  • 我还遇到了另一个错误:第25:6行:React Hook useEffect缺少依赖项:“id”。包括它或删除依赖项数组react hooks/dep。 我猜这个错误是由于id设置在渲染外部造成的
  • import React,{useState,useffect}来自“React”;
    从“axios”导入axios;
    函数datafetching(){
    const[post,setPost]=useState({});
    const[id,setId]=useState(1);
    const[search,setSearch]=useState(1);
    常量handleClick=()=>{
    控制台日志(post);
    设置搜索(post);
    };
    useffect(()=>{
    axios
    .得到(`https://jsonplaceholder.typicode.com/posts/${id}`)
    。然后((res)=>{
    控制台日志(res);
    setPost(res.data);
    })
    .catch((错误)=>{
    控制台日志(err);
    setPost(err);
    });
    },[搜索];
    返回(
    投递
    setId(e.target.value)}/>
    {post.title}
    );
    }
    导出默认数据绑定;
    
    我不确定您在使用
    搜索
    状态查找什么。但是如果您只想在有人点击
    fetchpost
    按钮时提取组件,我可能会添加一个
    searchId
    状态。这解决了
    useffect
    hook的所有复杂性。我知道您希望有一个受控输入,因此需要
    id
    状态。在这种情况下,专门为用于获取的id添加一个额外的状态变量并不可怕

    从“react”导入{useffect,useState};
    从“axios”导入axios;
    函数datafetching(){
    const[post,setPost]=useState({});
    const[id,setId]=useState(1);
    const[searchId,setSearchId]=useState(id)
    const[search,setSearch]=useState(1);
    常量handleClick=()=>{
    控制台日志(post);
    设置搜索(post);
    设置搜索(id);
    };
    useffect(()=>{
    axios
    .得到(`https://jsonplaceholder.typicode.com/posts/${searchId}`)
    。然后((res)=>{
    控制台日志(res);
    setPost(res.data);
    })
    .catch((错误)=>{
    控制台日志(err);
    setPost(err);
    });
    },[searchId]);
    返回(
    投递
    setId(e.target.value)}/>
    {post.title}
    );
    }
    导出默认数据绑定
    • 1)每次单击按钮时,代码都会获取数据,因为当您将
      [search]
      作为
      useffect()
      的第二个参数提供给
      useffect()
      时,您要求每次
      search
      变量更改时都执行
      useffect()

      您正在使用“setSearch()”为一个对象设置
      search
      值,即使该对象的属性和相应的值与以前相同,在javascript看来,两个对象也永远不会相等。您可以测试它并查看
      console.log({}==={})
      输出
      false

      因此,由于您在
      handleClick()
      函数中使用“setSearch()”将
      search
      值设置为对象,因此每次单击按钮时,它都会自动触发
      useffect()
      并获取数据

    • 2)React看到您在
      useffect()
      中使用了
      id
      变量,因此它假设您希望在更新
      id
      时运行此效果。它不知道您是如何更新
      id
      变量的,它会试图保护您不被意外地使用旧获取的数据,例如,在几个月后,您决定添加另一种方式来修改
      id
      变量(可能是页面底部的“获取下一篇文章”按钮)

      这是
      useffect()
      有用性的一部分-无论
      id
      如何更改,数据都将被提取,因此您不必记住手动执行
      setSearch(id)
      之类的操作,1)很容易忘记,2)当有人第一次阅读代码时,其意图很模糊

    • 解决方案:我能想到的在没有更多上下文的情况下修复代码的最简单方法是更改
      handleClick()
      函数,使其将
      search
      设置为
      id
      (将是一个数字),而不是
      post
      (将是一个数字) 对象并始终触发
      useffect()
      函数,请参见2)


    你的逻辑暗示了以下几点

    初始值:

    const [post, setPost] = useState({});
    const [id, setId] = useState(1);
    const [search, setSearch] = useState(1);
    
    第一次单击后的值(假设:输入为2):

    第二次单击后的值(再次输入为2):

    如您所见,状态值仍在更改。
    一个最简单的解决方案是从handleClick函数调用fetch(并将
    搜索
    状态全部调用)。

    您说“即使依赖项数组对象保持不变”,但它没有。每次单击时都会更改对象,因为调用axios时,它会使用
    setPost
    ,这会更改
    post
    ,而下一次
    handleClick
    很可能会使用
    search
    在第一次单击后将
    {/*post 1 response*/}
    ,由于第一篇帖子是在页面加载时获取并保存为
    post
    ,所以在您单击按钮之前,除非您非常快并且在请求完成之前单击:)我发现在开发React应用程序时,这些超快速的状态更改最难在您的头脑中保持。即使在第二次、第三次、第四次点击之后,点击值也会被视为发生了变化,即使它是
    {/*post2response*/}
    {/*post2response*/}
    ,因为在javascript中两个对象是不相等的(请参见我的答案或只是
    控制台.log({}==={}
    )是的,您是100%正确:)谢谢您的帮助!
    const [post, setPost] = useState({});
    const [id, setId] = useState(1);
    const [search, setSearch] = useState(1);
    
    const [post, setPost] = useState({ /* post 2 response */ });
    const [id, setId] = useState(2);
    const [search, setSearch] = useState({});
    
    const [post, setPost] = useState({ /* post 2 response */ });
    const [id, setId] = useState(2);
    const [search, setSearch] = useState({ /* post 2 response */ });