setState는 React의 중요한 부분으로 구성 요소 상태에 대한 변경 사항을 대기열에 추가하고 업데이트된 상태로 이 구성 요소와 하위 구성 요소를 다시 렌더링해야 함을 React에 알립니다. 다음 기사는 React의 setState 메커니즘을 이해하는 데 도움이 될 것입니다.
state
는 React
에서 중요한 개념입니다. 우리는 React
가 상태 관리를 통해 구성 요소를 관리한다는 것을 알고 있습니다. 그렇다면 React
는 구성 요소의 상태를 어떻게 제어하며, 구성 요소를 관리하기 위해 상태를 어떻게 사용합니까? [관련 권장 사항: Redis 동영상 튜토리얼]state
是React
中的重要概念。我们知道,React
是通过状态管理来实现对组件的管理。那么,React
是如何控制组件的状态的,又是如何利用状态来管理组件的呢?【相关推荐:Redis视频教程】
我们都知道,React
通过this.state
来访问state
,通过this.setState()
方法更新state
。当this.setState()
被调用的时候,React
会重新调用render
方法来重新渲染UI
。
setState
已经是我们非常熟悉的一个API
,然而你真的了解它吗?下面我们将一起来解密setState
的更新机制。
大家刚开始写React
的时候,通常会写出 this.state.value = 1
这样的代码,这是完全错误的写法。
注意:绝对不要直接修改 this.state,这不仅是一种低效的做法,而且很有可能会被之后的操作替换。
setState
通过一个队列机制实现state
更新。当执行setState
时,会将需要更新的state
合并后放入状态对列,而不会立刻更新this.state
,队列机制可以高效地批量更新state
。如果不通过setState
而直接修改this.state
的值,那么该state
将不会被放入状态队列中,当下次调用setState
并对状态队列进行合并时,将会忽略之前直接被修改的 state
,而造成无法预知的错误。
因此,应该使用 setState
方法来更新 state
,同时 React
也正是利用状态队列机制实现了 setState
的异步更新,避免频繁地重复更新 state
。相关代码如下:
// 将新的state合并到状态更新队列中 var nextState = this._processPendingState(nextProps, nextContext); // 根据更新队列和 shouldComponentUpdate 的状态来判断是否需要更新组件 var shouldUpdate = this._pendingForceUpdte || !inst.shouldCompoonentUpdate || inst.shouldComponentUpdate(nextProps, nextState, nextContext0;
当调用setState
时,实际上会执行 enqueueSetState
方法,并对 partialState
以及 _pendingStateQueue
更新队列进行合并操作,最终操作 enqueueSetState
执行 state
更新。
而 performUpdateIfNecessary
方法会获取 _pendingElement、_pendingStateQueue、_pendingForceUpdate
,并调用 receiveComponent
和 updateComponent
方法进行组件更新。
如果在 shouldComponetUpdate
或 componentWillUpdate
方法中调用 setState
, 此时 this._pendingStateQueue != null
, 则 performUpateIfNecessary
方法就会调用 updateComponent
方法进行组件更新,但 updateComponent
方法又会调用 shouldComponentUpdate
和 componentWillUpdate
方法,因此造成循环调用,使得浏览器内存占满后崩溃。
既然 setState
最终是通过 enqueueUpate
执行 state
更新,那么 enqueueUpdate
到底是如何更新 state
的呢?
首先,看看下面这个问题,你是否能够正确回答呢?
import React, { Component } from 'react' class Example extends Component { constructor() { super() this.state = { val: 0 } } componentDidMount() { this.setState({val: this.state.val + 1}) console.log(this.state.val) this.setState({val: this.state.val + 1}) console.log(this.state.val) setTimeout(() => { this.setState({val: this.state.val + 1}) console.log(this.state.val) this.setState({val: this.state.val + 1}) console.log(this.state.val) },0) } render() { return null } }
上述代码中, 4 次 console.log
打印出来的 val
分别是:0、0、2、3
。
假如结果与你心中的答案不完全相同,那么你是否想知道 enqueueUpdate
setState
调用栈,注意其中核心的状态判断。
setState
简化调用栈
到底是怎么导致 setState
우리 모두 알고 있습니다, React
는 this.state
를 통해 state
에 액세스하고 this.setState()
메서드를 통해 state
를 업데이트합니다. . this.setState()
가 호출되면 React
는 UI
를 다시 렌더링하기 위해 render
메서드를 다시 호출합니다. .
setState
는 이미 우리에게 매우 익숙한 API
인데, 정말 이해하고 계시나요? 아래에서는 setState
의 업데이트 메커니즘을 해독합니다. 🎜React
작성을 시작할 때 일반적으로 this.state.value = 1 </을 작성합니다. code> 그런 코드는 완전히 잘못된 코드입니다. 🎜<blockquote>🎜참고: 절대로 this.state를 직접 수정하지 마세요. 이는 비효율적인 접근 방식일 뿐만 아니라 후속 작업으로 대체될 가능성도 있습니다. 🎜</blockquote>🎜<code>setState
는 대기열 메커니즘을 통해 상태
업데이트를 구현합니다. setState
가 실행되면 업데이트가 필요한 state
가 병합되어 상태 큐에 들어가고 this.state
는 업데이트되지 않습니다. 즉시 업데이트됩니다. 메커니즘은 상태
를 일괄적으로 효율적으로 업데이트할 수 있습니다. setState
없이 this.state
의 값을 직접 수정하면 다음에 호출할 때 state
가 상태 대기열에 추가되지 않습니다. setState
를 사용하여 상태 대기열을 병합하면 이전에 직접 수정된 상태
가 무시되어 예측할 수 없는 오류가 발생합니다. 🎜🎜따라서 state
를 업데이트하려면 setState
메서드를 사용해야 합니다. 동시에 React
는 상태 대기열 메커니즘을 사용하여 < code>setState 코드의 비동기 업데이트>는 상태
의 빈번한 반복 업데이트를 방지합니다. 해당 코드는 다음과 같습니다. 🎜import ReactDOM, { unstable_batchedUpates } from 'teact-dom' unstable_batchedUpates(() => { this.setState(val: this.state.val + 1) this.setState(val: this.state.val + 1) })
setState
호출 시 enqueueSetState</code > 실제로 실행됩니다. > 메서드를 실행하고 <code>partialState
및 _pendingStateQueue
업데이트 대기열에서 병합 작업을 수행하고, 마지막 작업 enqueueSetState
는 >상태
업데이트. 🎜🎜 performUpdateIfNecessary
메서드는 _pendingElement, _pendingStateQueue, _pendingForceUpdate
를 획득하고 receiveComponent
및 updateComponent
메서드를 호출하여 업데이트합니다. 구성 요소. 🎜🎜setState
가 shouldComponetUpdate
또는 comComponentWillUpdate
메서드에서 호출되면 this._pendingStateQueue != null
입니다. performUpateIfNecessary
메소드는 updateComponent
메소드를 호출하여 구성요소를 업데이트하지만 updateComponent
메소드는 shouldComponentUpdate
를 호출하고 < code> componentWillUpdate 메서드로 인해 루프 호출이 발생하여 메모리가 가득 찬 후 브라우저가 중단됩니다. 🎜🎜🎜setState
는 궁극적으로 enqueueUpate
를 통해 상태
업데이트를 수행하므로 어떻게 해야 할까요? enqueueUpdate
가 상태
를 업데이트하나요? 🎜🎜우선, 다음 질문을 잘 보세요. 정답을 맞힐 수 있나요? 🎜rrreee🎜위 코드에서 console.log
에 의해 4번 출력된 val
은 0, 0, 2, 3
입니다. 🎜🎜결과가 마음속에 있는 대답과 정확하게 일치하지 않으면 enqueueUpdate
가 실제로 무엇을 하는지 알고 싶으십니까?
아래 그림은 단순화된 setState
호출 스택입니다. 핵심 상태 판단에 주의하세요. 🎜🎜🎜🎜< code>setState호출 스택 단순화🎜setState
의 다양한 성능으로 이어지나요? 🎜我们先要了解事务跟 setState
的不同表现有什么关系。首先,我们把4次 setState
简单归类,前两次属于一类,因为他们在同一次调用栈中执行,setTimeout
中的两次 setState
属于另一类,因为他们也是在同一次调用栈中执行。我们分析一下这两类 setState
的调用栈。
在 componentDidMount
中直接调用的两次 setState
,其调用栈更加复杂;而setTimeout
中调用的两次 setState
,其调用栈则简单很多。下面我们重点看看第一类 setState
的调用栈,我们发现了 batchedUpdates
方法,原来早在 setState
调用前,已经处于batchedUpdates
执行的事务中了。
那batchedUpdates
方法,又是谁调用的呢?我们再往前追溯一层,原来是 ReactMount.js 中的 _renderNewRootComponent
方法。也就是说,整个将React组件渲染到DOM中的过程就处于一个大的事务中。
接下来的解释就顺理成章了,因为在componentDidMount
中调用setState
时,batchingStrategy
的 isBatchingUpdates
已经被设为true
,所以两次setState
的结果并没有立即生效,而是被放到了dirtyComponents
中。这也解释了两次打印 this.state.val
都是 0
的原因,因为新的 state
还没有被应用到组件中。
componentDidMount
中setState
的调用栈
setTimeout
中setState
的调用栈
再反观 setTimeout
中的两次setState
,因为没有前置的 batchedUpdate
调用,所以 batchingStrategy
的 isBatchingUpates
标志位是false
,也就导致了新的 state
马上生效,没有走到 dirtyComponents
分支。也就是说,setTimeout
中第一次执行 setState
时,this.state.val
为 1
, 而 setState
完成打印后打印时 this.state.val
变成了2
。第二次的 setState
同理。
前面介绍事务时,也提到了其在 React
源码中的多处应用,像 initialize、perform、close、closeAll、motifyAll
等方法出现在调用栈中,都说明当前处于一个事务中。
既然事务这么有用,我们写应用代码时能使用它吗?很可惜,答案是不能。尽管React
不建议我们直接使用事务,但在 React 15.0
之前的版本中还是为开发者提供了 batchedUpdates
方法,它可以解决针对一开始例子中setTimeout
里的两次 setState
导致两次 render
的情况:
import ReactDOM, { unstable_batchedUpates } from 'teact-dom' unstable_batchedUpates(() => { this.setState(val: this.state.val + 1) this.setState(val: this.state.val + 1) })
在 React 15.0
以及之后版本中,已经彻底将 batchUpdates
这个 API
移除了,因此不再建议开发者使用它。
在使用React
的setState
的过程中,了解setState
的实现原理,对setState
异步更新、setState
循环调用风险、setState
调用栈等进行更加全面的了解,才能让我们在遇到相关问题的时候更加游刃有余。
更多编程相关知识,请访问:编程入门!!
위 내용은 React의 setState 업데이트 메커니즘에 대한 심층적인 이해의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!