6

useEffect如果像这样的代码由的依赖重新渲染,

// ...
const Test = () => {
  // ...
  
  const value1 = "test1"
  
  const func1 = () => {
    // do something1
  }
  
  useEffect(() => {
    const value2 = "test2"
  
    const func2 = () => {
      // do something2
    }
  }, [sth])
  
  return (
    // ...
  )
}

value1& value2& func1&是否func2重新分配给内存?

我很好奇它,与优化有关。

4

3 回答 3

4

简短的回答,是的。每次函数运行时,旧值将被垃圾收集,新的原始值将被分配到内存中,并且将为函数和对象创建新的引用。

但“不那么短”答案的真正问题是“它是否会显着影响性能?” . 答案是……取决于。在大多数情况下,它不会(请参阅有关它的文档)。但是在某些情况下,您需要进行一些更改才能使用useCallback和使用useMemo.

还值得一提(如Shivam Jha 的回答中所说),触发器useEffect不一定会导致重新渲染(DOM 绘制),因为此过程首先发生在虚拟 DOM 上,并且只会在必要时保留在真实 DOM 中。

我将在这里留下一些关于此讨论的其他参考资料。

Dan Abramov 关于记忆一切的推文(另请查看回复)

Kent C. Dodds 关于渲染性能的文章

Felix Gerschau 关于何时渲染发生的文章

于 2021-03-04T04:09:51.723 回答
3

value1 & value2 & func1 & func2 是否重新分配给内存?

简而言之,答案是肯定的。

如果你看它是什么会更清楚:Test是一个函数,所以每次调用该函数时,函数范围内的所有变量(大括号)都会重新声明和重新分配。

让我们深入了解一下细节:

value1并且func1在函数的主体中,因此每次调用函数时它们都会被声明和分配,它们根本不相关,它们只是具有相同的名称。

value2而是func2在一个 useEffect 钩子中声明,并声明了依赖sthsth

如果你想优化value1它不会在每次渲染时改变,你可以useMemo这样使用钩子:

const value1 = React.useMemo(() => {
  return "test1"; //here you might have a more complicate way to determine value1
}, []); //array of dependencies like for `useEffect`, so `value1` will be recalculated only if any of the values provided in here change. by leaving it empty value1 will always be the **same** variable

useCallback您也可以使用钩子对函数进行类似的优化

于 2021-03-04T04:27:25.713 回答
1

根据文档:

useEffect 有什么作用?通过使用这个 Hook,你告诉 React 你的组件需要在渲染之后做一些事情。React 会记住您传递的函数(我们将其称为“效果”),并在执行 DOM 更新后稍后调用它。在这个效果中,我们设置了文档标题,但我们也可以执行数据获取或调用其他一些命令式 API。

此外,它不re-renders执行代码,而是在传递给它的依赖项发生更改时再次运行代码

提示:通过跳过效果优化性能描述了由于在每次渲染后清理或应用效果而导致的性能问题。

(setTimeOut, etc)此外,您可以释放分配的内存(如果没有自动释放)或在运行代码后使用useEffect 和 cleanup运行一些副作用。基本上在 return 函数中执行 useEffect 之后要运行的所有操作:

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    // Specify how to clean up after this effect:
    return function cleanup() {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });
于 2021-03-04T04:02:03.787 回答