Reactjs 我应该如何删除警告;React Hook useEffect缺少依赖项“;?
我有一个在Reactjs 我应该如何删除警告;React Hook useEffect缺少依赖项“;?,reactjs,react-hooks,Reactjs,React Hooks,我有一个在useffect中使用的函数,单击事件,然后抛出警告“React Hook useffect有一个缺少的依赖项”,我应该如何删除该警告 // location is react router location const Component = ({ location }) => { const [data, setData] = useState(null); const fetchData = () => { const { id } = parseL
useffect
中使用的函数,单击事件,然后抛出警告“React Hook useffect有一个缺少的依赖项”,我应该如何删除该警告
// location is react router location
const Component = ({ location }) => {
const [data, setData] = useState(null);
const fetchData = () => {
const { id } = parseLocation(location);
fetchDataFromServer(id).then(data => setData(data));
}
useEffect(() => {
fetchData();
}, [location]);
return (
<div>
{data}
<button onClick={fetchData)}>reload</button>
</div>
);
}
//位置是路由器位置
常量组件=({location})=>{
const[data,setData]=useState(null);
常量fetchData=()=>{
const{id}=parseLocation(位置);
fetchDataFromServer(id).then(data=>setData(data));
}
useffect(()=>{
fetchData();
},[地点];
返回(
{data}
重新加载
);
}
然后我尝试了这个,但是警告仍然存在
// location is react router location
const Component = ({ location }) => {
const [data, setData] = useState(null);
const fetchData = (l) => {
// l is location
const { id } = parseLocation(l);
fetchDataFromServer(id).then(data => setData(data));
}
useEffect(() => {
fetchData(location);
}, [location]);
return (
<div>
{data}
<button onClick={() => fetchData(location)}>reload</button>
</div>
);
}
//位置是路由器位置
常量组件=({location})=>{
const[data,setData]=useState(null);
常量fetchData=(l)=>{
//l是位置
const{id}=parseLocation(l);
fetchDataFromServer(id).then(data=>setData(data));
}
useffect(()=>{
获取数据(位置);
},[地点];
返回(
{data}
fetchData(位置)}>重新加载
);
}
穷举deps规则的要点是防止钩子读取过时的道具或状态。问题在于,由于fetchData
是在组件中定义的,因此就linter而言,它可能正在访问过时的props
或状态(通过闭包)
一种解决方案是从组件中拉出fetchData
,并传递它所需的一切:(它已经被传递到了位置):
const fetchData=(l,setData)=>{
//l是位置
const{id}=parseLocation(l);
fetchDataFromServer(id).then(data=>setData(data));
}
常量组件=({location})=>{
const[data,setData]=useState(null);
useffect(()=>{
获取数据(位置、设置数据);
},[地点];
返回(
{data}
fetchData(位置,setData)}>reload
);
}
由于fetchData
不是在组件外部定义的,所以linter知道它不会访问state或props,因此对于过时的数据来说这不是问题
不过,要明确的是,从运行时的角度来看,您的原始解决方案是正确的,因为fetchData
不读取状态或道具,但linter不知道这一点
您可以简单地禁用linter,但是以后很容易意外地引入bug(如果fetchData
被修改过)。最好使用linter规则验证正确性,即使这意味着对代码进行一些轻微的重构
替代解决方案
另一种利用闭包而不是将位置传递到fetchData
的解决方案:
const Component = ({ location }) => {
const [data, setData] = useState(null);
const fetchData = useCallback(() => {
// Uses location from closure
const { id } = parseLocation(location);
fetchDataFromServer(id).then(data => setData(data));
// Ensure that location isn't stale
}, [location]);
useEffect(() => {
fetchData();
// Ensure that fetchData isn't stale
}, [fetchData]);
return (
<div>
{data}
<button onClick={fetchData}>reload</button>
</div>
);
}
const组件=({location})=>{
const[data,setData]=useState(null);
const fetchData=useCallback(()=>{
//从闭包中使用位置
const{id}=parseLocation(位置);
fetchDataFromServer(id).then(data=>setData(data));
//确保位置没有过时
},[地点];
useffect(()=>{
fetchData();
//确保fetchData没有过时
},[fetchData]);
返回(
{data}
重新加载
);
}
这种方法可以避免每次调用时将位置
传递到获取数据
。然而,使用这种方法时,重要的是要确保避免过时的状态和道具
如果将[fetchData]
dep省略到useffect
,则该效果将只运行一次,并且在位置更改时不会提取新数据
但是,如果在useffect
的deps中有fetchData
,但没有在useCallback
中包装fetchData
,则fetchData
函数在每次渲染时都是一个新函数,这将导致useffect
运行每次渲染(这将是不好的)
通过在useCallback
中进行包装,只要位置发生变化,fetchData
函数就只是一个新函数,这会导致useffect
在适当的点运行。您可以将//eslint禁用}、[location]上方的下一行
似乎可以将fetchData添加到依赖项数组中also@ArnoldGandarillas如果有人有过梁错误,我不会建议禁用过梁错误,除非您解释为什么忽略该问题是安全的。在这种情况下,我不认为这是最好的选择。@SeanMC这将导致useffect
运行每个渲染-我认为它实际上会导致一个无限循环,因为每个渲染将触发fetchData
,这将触发setState
,从而导致一个新的渲染。我强烈建议阅读Dan Abramov的;我试图在我的答案中给出一个简略的版本。它可以工作,但需要将setData
传递到fetchData
<代码>常量fetchData=({location,setData})=>{/…}
啊,捕捉得好。固定的。就我个人而言,在这种情况下,我可能会自己使用useCallback
表单。