React.useState如何再次启动包含函数



假设我们有一个简单的功能组件:

export function MyComp(){
const [state, setState] = React.useState({foo:1});
setTimeout(() => setState({foo:2}, 45);
return (
<div> {state.foo} </div>
)
}

如果setState没有再次神奇地调用MyComp(),它将如何重新渲染?如果它神奇地再次调用MyComp(),这是怎么回事?

在代码中,setState不会神奇地调用组件,而是触发重新渲染。因此,在您的情况下执行setState(someValue)是导致MyComp重新渲染的原因。您可以在React文档中阅读更多关于这一点和钩子的信息:https://reactjs.org/docs/hooks-state.html#recap

希望它能回答你的问题!

我不是React机制本身的专家,但在使用一些CS概念的非常简化的版本中,它背后的想法可能如下:

首先,React必须有一个应用程序中所有组件的列表,我们将用列表来简化它,但实际上它是一棵树:

const nodes = <>
<h1>My Counter</h1>
<Counter />
<div>
</>

因此,在这一点上,如果您的应用程序是平面的,DummyReactDOM.render(nodes)将创建这些节点的列表":

nodes = [ h1, Counter, div ]

当调用useState时会变得棘手,React将要做的是保存某种状态(记忆状态(,例如Counter节点可能看起来像这样:

function Counter() {
[ counter, setCounter ] = useState(0);
}

这将为节点添加一个状态:

node Counter = {
state : {
counter: 0
next  : null
}
}

现在,当我们点击组件并调用setCounter(counter + 1)时会发生什么?将下一个状态添加到队列中:

node Counter = {
state : {
counter : 0,
next    : {
state : {
counter : 1, // <-- setCounter(counter + 1 happens)
next    : null,
}
}
}
}
// firstState.next -> secondState.next -> null

现在,调度器是了解哪些组件需要重新渲染的主要思想。以下是一种非常不现实但易于理解的看待方式:

while (true) {
// sleepForABit();
if (currentNode.state.next !== null && currentNode.state !== currentNode.state.next) {
currentNode.state = currentNode.state.next;
currentNode.component.render(); // or functionalComponent() call
}
currentNode = currentNode.next
}

如果它是一个节点列表,这是一个简单的情况,但很明显,由于节点需要重新渲染,React将检查其子节点。需要注意的是,重新渲染实际上并没有那么昂贵,昂贵的部分是重新创建DOM节点(以及在较小程度上更新它们(,因此检查子节点的性能大多相当高。

希望这能有所帮助!

如果您想知道为什么我们可以在不总是使用counter = 0的情况下执行setCounter(counter + 1),React保证在某些事件上重新渲染节点(onClick是众多事件之一(。

相关内容

  • 没有找到相关文章

最新更新