React Hooks 背后的 JavaScript 机制是如何工作的?

2024-06-09

我的问题涉及使 React hooks 成为可能的 Javascript 机制。

React 最近的发展允许我们创建钩子,即。对于 React 状态,使用简单的函数,例如:

function App () {
  const [someVar, setSomeVar] = useState('someVarDefaultValue');
  return (
    <div 
      onClick={() => setSomeVar('newValue')}>{someVar}
    </div>
  );
}

钩子useState返回一个带有访问器和修改器的数组,我们在 App 函数中通过数组分解来使用它们。

因此,在底层,该钩子看起来像这样(只是伪代码):

function useState(defaultValue) {
  let value = defaultValue;

  function setValue(val) {
    value = val;
  }

  return [value, setValue];
}

当您在 JS 中尝试这种方法时,它不会起作用 - 如果您使用,从数组分解的值将不会更新setValue某处。即使您使用value作为一个对象,而不是一个原始对象defaultValue.

我的问题是JS中的hook机制是如何工作的?

从我在 React 中看到的源代码 https://github.com/facebook/react/blob/c2a2d8a539bf02e40c43d36adc2826e228f30955/packages/react-dom/src/server/ReactPartialRendererHooks.js#L165它使用减速器功能和 Flow 的类型检查。对于我来说,要理解大局,要遵循该代码是很棘手的。

这个问题不是关于如何在 React 中编写自定义钩子 https://reactjs.org/docs/hooks-custom.html.

在这个问题中回答的 React 状态管理上下文中,钩子如何在后台工作也不是问题:React Hooks - 幕后发生了什么? https://stackoverflow.com/questions/53729917/react-hooks-whats-happening-under-the-hood


状态值必须存储在外部useState函数,在组件实例的某些内部表示中,以便它在调用之间返回持久的结果。此外,设置该值必须导致在调用它的组件上重新渲染:

// useState must have a reference to the component it was called in:
let context;

function useState(defaultValue) {
  // Calling useState outside of a component won't work as it needs the context:
  if (!context) {
    throw new Error("Can only be called inside render");
  }

  // Only initialize the context if it wasn't rendered yet (otherwise it would re set the value on a rerender)
  if (!context.value) {
    context.value = defaultValue;
  }

  // Memoize the context to be accessed in setValue
  let memoizedContext = context;

  function setValue(val) {
    memoizedContext.value = val;

    // Rerender, so that calling useState will return the new value
    internalRender(memoizedContext);
  }

  return [context.value, setValue];
}

// A very simplified React mounting logic:
function internalRender(component) {
  context = component;
  component.render();
  context = null;
}

// A very simplified component
var component = {
  render() {
    const [value, update] = useState("it");
    console.log(value);
    setTimeout(update, 1000, "works!");
  }
};

internalRender(component);

那么当setValue被调用,组件重新渲染,useState将再次被调用,并返回新值。

上面的例子非常简单。以下是 React 所做的一些不同的事情:

  1. 状态不存储在“上下文属性”中,而是存储在链接列表中。每当useState被调用时,链表前进到下一个节点。这就是为什么你不应该在分支/循环中使用钩子。
  2. The setState函数被缓存并且每次都返回相同的引用。
  3. 重新渲染不会同步发生。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

React Hooks 背后的 JavaScript 机制是如何工作的? 的相关文章

随机推荐