Javascript 即使依赖关系数组对象在Reactjs中保持不变,也可以单击按钮重新呈现页面
我使用的是React 17.0.1。我无法理解以下几点: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
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 */ });