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
表单。