如果清理函数依赖于依赖值,React 如何跟踪它?

问题描述 投票:0回答:1

在React网站的这段代码中:

import { useState, useEffect } from 'react';

export default function App() {
  const [position, setPosition] = useState({ x: 0, y: 0 });
  const [canMove, setCanMove] = useState(true);

  useEffect(() => {
    function handleMove(e) {
      setPosition({ x: e.clientX, y: e.clientY });
    }
    if (canMove) {
      window.addEventListener('pointermove', handleMove);
      return () => window.removeEventListener('pointermove', handleMove);
    }
  }, [canMove]);

  return (
    <>
      <label>
        <input type="checkbox"
          checked={canMove}
          onChange={e => setCanMove(e.target.checked)} 
        />
        The dot is allowed to move
      </label>
      <hr />
      <div style={{
        position: 'absolute',
        backgroundColor: 'pink',
        borderRadius: '50%',
        opacity: 0.6,
        transform: `translate(${position.x}px, ${position.y}px)`,
        pointerEvents: 'none',
        left: -20,
        top: -20,
        width: 40,
        height: 40,
      }} />
    </>
  );
}

useEffect 依赖于变量 canMove。因此,当 canMove 为 true 且效果仅运行一次且对于浏览器中的每个指针移动时,都会触发添加的事件侦听器。当 canMove 为 false 时,React 应该在设置之前先运行清理。

但是 return 语句是在 canMove 的条件下的,现在它是 false,所以控件不应该进入那里。那么,当 Effect 设置运行时,React 会记录清理函数吗?如果这样做,React 会存储清理函数,直到触发下一个 useEffect。

reactjs react-hooks
1个回答
0
投票

但是 return 语句是在 canMove 的条件下的,现在它是 false,所以控件不应该进入那里。那么,当 Effect 设置运行时,React 会记录清理函数吗?

是的,react 保留对前一个效果的清理函数的引用并调用它。

如果这样做,React 会存储清理函数,直到触发下一个 useEffect。

useEffect 的实现(在第一个之后的渲染上)称为 updateEffectImpl,在此处找到。它调用函数

pushEffect
,然后将结果值保存到
hook.memoizedState
pushEffect
创建并返回一个包含“create”函数的对象。
create
是您传递给使用效果的函数,它可能会也可能不会返回清理函数。

hook.memoizedState = pushEffect(
    HookHasEffect | hookFlags,
    create,
    inst,
    nextDeps,
);

稍后,在 ReactFiberCommitWork.js 中,调用

create
函数并保存销毁函数(如果有)。

const create = effect.create;
const inst = effect.inst;
destroy = create();
inst.destroy = destroy;
© www.soinside.com 2019 - 2024. All rights reserved.