【问题标题】:react-hooks/exhaustive-deps warning or infinite loop?react-hooks/exhaustive-deps 警告还是无限循环?
【发布时间】:2021-04-13 02:50:20
【问题描述】:

我有一个mediaType 变量,当它改变时,currentSelectedMedia 需要被过滤。在这种情况下,我会收到 react-hooks/exhaustive-deps 警告。

  /**
  data example:

  currentSelectedMedia = [
    { id: '1', mediaType: '1', name: 'facebook'},
    { id: '2', mediaType: '2', name: 'twitter'}
  ]
  **/

  useEffect(() => {
    setCurrentSelectedMedia(currentSelectedMedia.filter(item => item.mediaType === mediaType))
  }, [mediaType])

如果我将currentSelectedMedia添加到依赖数组中,就会导致无限循环。

警告是正确的,死循环的原因也很明显。 但是我怎样才能逃脱呢?

【问题讨论】:

  • 为什么要把currentSelectedMedia放在依赖列表中?你这样做是为了达到什么目的?认为我们需要更多背景信息。
  • 您能否发布id 的值以及mediaDataMap 包含哪些数据?
  • @Jayce444 我想避免警告,react-hooks/exhaustive-deps
  • @Yadab 我编辑示例,不关心mediaDataMap,这是不相关的
  • 只需使用 currentSelectedMedia.filter(item => item.mediaType === mediaType) 渲染内容,您真的不需要使用 useEffect,因为您在 mediaType 更改时调用它

标签: reactjs react-hooks


【解决方案1】:

您收到 react-hooks/exhaustive-deps 警告或无限循环,因为每次 mediaType 状态发生变化时都会触发您的 useEffect 钩子; 在您的 useEffect 方法中,您正在设置 mediaType 状态的值;

要解决这个问题,你可以有两个不同的状态,或者只是一个设置mediaType 的普通函数,或者只是创建一个变量,当你的状态发生变化时过滤数据。 这取决于您如何从其他地方设置您的 mediaType 状态。

const filteredData = currentSelectedMedia.filter(item => item.mediaType === mediaType);

使用过滤数据来呈现数据。

【讨论】:

  • filteredMedia 必须是一个状态变量,它可以被其他逻辑修改并导致重新渲染
  • 会导致重新渲染,因为你的mediaType变量是状态变量。
【解决方案2】:

我相信您想要的是获得过滤后的选定媒体。

但是,在这种情况下使用 useEffect 可能不是最合适的。您可能需要考虑 useMemo

const filteredMedia = useMemo(() => {
    return currentSelectedMedia.filter(item => item.mediaType === mediaType)
}, [currentSelectedMedia, mediaType] )

然后您可以在渲染中使用filteredMedia

只有在currentSelectedMediamediaType 更改时,该值才会重新过滤

上面几乎等价于

 const filteredMedia = currentSelectedMedia.filter(item => item.mediaType === mediaType)

不同之处在于 - useMemo 是“记忆的”,因此不会在每次渲染时重新计算。

小型数组和计算的性能差异很小,在处理庞大的列表和复杂的计算时可以看到明显的性能提升。

【讨论】:

  • 我 +1 这个答案,因为 useMemo 肯定会工作,但 useMemo 在存储复杂计算时最有效。在这种情况下,性能成本超过了功能优势。
  • 但是在我的情况下,filteredMedia 必须是一个状态变量,它可以被其他逻辑修改并导致重新渲染,我稍后会给出一个完整的演示。
  • 您可以修改任何状态,任何逻辑,只需将状态添加到依赖列表中即可。将 useMemo 视为“状态鸡尾酒”。您可以管理(值)的许多独立的简单状态,并使用 useMemo 将所有这些值组合成您可以在渲染中使用的东西。
【解决方案3】:

useEffect 将在挂载时触发,并且每次其依赖项之一发生更改时。如果您将 currentSelectedMedia 添加到它的依赖项列表中,并且您还在您的 useEffect 中修改 currentSelectedMedia 导致 无限循环。

我会简单地使用相同的逻辑来改变mediaType(很可能是[action]Handler函数)和setCurrentSelectedMedia

【讨论】:

    猜你喜欢
    • 2020-05-01
    • 2020-11-20
    • 1970-01-01
    • 2021-04-15
    • 2020-01-18
    • 1970-01-01
    • 2021-09-03
    • 2021-02-18
    • 2020-06-22
    相关资源
    最近更新 更多