[React 깊이] setState 의 실행 메커니즘
다음 과 같은 몇 가지 문 제 는 우리 가 실제 개발 에서 자주 만 나 는 장면 이다. 다음은 몇 가지 간단 한 예시 코드 로 복원 하 자.
1. setState 는 동기 화 입 니까? 비동기 입 니까? 왜 어떤 때 는 즉시 업데이트 결 과 를 얻 지 못 하고 어떤 때 는 가능 합 니까?
1.1 갈고리 함수 와 React 합성 이벤트 의
setState
현재 두 개의 구성 요소 가 있 습 니 다. componentDidMount() {
console.log('parent componentDidMount');
}
render() {
return (
);
}
구성 요소 내부 에 같은 코드 를 넣 고
Setstate1
의 componentDidMount
에 동기 화 지연 코드 를 넣 고 인쇄 지연 시간: componentWillUpdate() {
console.log('componentWillUpdate');
}
componentDidUpdate() {
console.log('componentDidUpdate');
}
componentDidMount() {
console.log('SetState setState');
this.setState({
index: this.state.index + 1
})
console.log('state', this.state.index);
console.log('SetState setState');
this.setState({
index: this.state.index + 1
})
console.log('state', this.state.index);
}
다음은 실행 결과 입 니 다.
설명:
setState
은 즉시 업데이트 되 지 않 습 니 다 didmount
가 있 으 면 부모 구성 요소 didmount
를 사용 한 다음 에 업 데 이 트 를 실행 합 니 다 1.2 비동기 함수 와 원생 사건 중의
setstate
?setTimeout
에서 호출 setState
(예 는 브 라 우 저 네 이 티 브 이벤트 및 인터페이스 리 셋 에서 실행 효과 와 같 음) componentDidMount() {
setTimeout(() => {
console.log(' setState');
this.setState({
index: this.state.index + 1
})
console.log('state', this.state.index);
console.log(' setState');
this.setState({
index: this.state.index + 1
})
console.log('state', this.state.index);
}, 0);
}
실행 결과:
설명:
didmount
에서 실행 setState
동기 업데이트 setState
한 번 만 효력 이 발생 합 니까?다음 코드 를 각각 실행 합 니 다:
componentDidMount() {
this.setState({ index: this.state.index + 1 }, () => {
console.log(this.state.index);
})
this.setState({ index: this.state.index + 1 }, () => {
console.log(this.state.index);
})
}
componentDidMount() {
this.setState((preState) => ({ index: preState.index + 1 }), () => {
console.log(this.state.index);
})
this.setState(preState => ({ index: preState.index + 1 }), () => {
console.log(this.state.index);
})
}
실행 결과:
1
1
2
2
설명:
setstate
은 한 번 합 쳐 진다 state
합병 되 지 않 음 소스 코드 가 복잡 하기 때문에 여기에 붙 이지 않 습 니 다. 관심 있 는 것 은
github
에 clone
한 부 를 올 린 다음 에 아래 의 절차 도 에 따라 한 번 걸 어 갈 수 있 습 니 다.1. 흐름 도
그림 이 잘 모 르 겠 어 요. 클릭 해서 원 도 를 볼 수 있어 요.
partialState
: setState
들 어 오 는 첫 번 째 매개 변수, 대상 또는 함수 _pendingStateQueue
: 현재 구성 요소 가 업 데 이 트 를 기다 리 고 있 는 state
대기 열 isBatchingUpdates
: react 는 현재 대량 업데이트 상태 에 있 는 지, 모든 구성 요소 가 공용 dirtyComponent
: 현재 업데이트 대기 상태 에 있 는 모든 구성 요소 대기 열 transcation
: react 의 사무 체 제 는 사무 호출 방법 에 따라 n 개 waper
대상 을 포장 하고 한 번 에 집행 한다. waper.init
, 호출 방법, waper.close
FLUSH_BATCHED_UPDATES
: 업 데 이 트 를 수행 하 는 waper
방법 은 하나 close
밖 에 없다 2. 실행 과정
위의 흐름 도의 문자 설명 을 대조 하면 대략 다음 과 같은 몇 단계 로 나 눌 수 있다.
partialState
매개 변 수 를 현재 구성 요소 인 스 턴 스 의 state 임시 저장 대기 열 에 저장 합 니 다.waper
방법 으로 업 데 이 트 를 기다 리 는 구성 요소 대기 열 을 옮 겨 다 니 며 업 데 이 트 를 순서대로 수행 합 니 다.componentWillReceiveProps
를 집행 한다.state
을 합 쳐 최종 업데이트 할 state 대상 을 얻 고 대기 열 을 비 웁 니 다.componentShouldUpdate
을 실행 하고 반환 값 에 따라 계속 업데이트 할 지 여 부 를 판단 한다.componentWillUpdate
를 집행 한다.render
componentDidUpdate
를 집행 한다.총화
1. 갈고리 함수 와 합성 이벤트 중:
react
의 생명주기 와 합성 사건 에서 react
는 여전히 그의 갱신 메커니즘 에 있 는데 이때 isBranchUpdate
는 true 이다.상기 과정 에 따 르 면 이 때 는 몇 번
setState
을 호출 하 든 업 데 이 트 를 실행 하지 않 고 업데이트 할 state
을 저장 _pendingStateQueue
하고 업데이트 할 구성 요 소 를 저장 합 니 다 dirtyComponent
.지난번 업데이트 메커니즘 이 실행 되면 생명주기 로 예 를 들 면 모든 구성 요소, 즉 최상 위 구성 요소
didmount
를 false 로 설정 합 니 다.이때 이전에 누 적 된 것 isBranchUpdate
을 집행 할 것 이다.2. 비동기 함수 와 네 이 티 브 이벤트 중
실행 체 제 를 보면
setState
자체 가 비동기 가 아니 라 호출 setState
할 때 setState
업데이트 과정 에 있 으 면 현재 업데이트 가 일시 적 으로 저장 되 고 지난번 업데이트 가 실 행 된 후에 실 행 될 때 이 과정 은 비동기 적 인 가상 을 준다.라 이 프 사이클 에 서 는 JS 의 비동기 시스템 에 따라 비동기 함 수 를 잠시 저장 하고 모든 동기 코드 가 실 행 된 후에 실 행 됩 니 다. 이때 지난번 업데이트 과정 이 실 행 됐 고
react
false 로 설정 되 었 으 며 위의 절차 에 따라 호출 isBranchUpdate
하면 바로 업 데 이 트 를 실행 하여 업데이트 결 과 를 얻 을 수 있 습 니 다.3.
setState
합병 메커니즘다음 프로 세 스
partialState
의 코드 를 보 겠 습 니 다. 이 함 수 는 _processPendingState
임시 저장 대기 열 을 합 친 것 이 고 마지막 으로 합 친 것 state
을 되 돌려 줍 니 다.
_processPendingState: function (props, context) {
var inst = this._instance;
var queue = this._pendingStateQueue;
var replace = this._pendingReplaceState;
this._pendingReplaceState = false;
this._pendingStateQueue = null;
if (!queue) {
return inst.state;
}
if (replace && queue.length === 1) {
return queue[0];
}
var nextState = _assign({}, replace ? queue[0] : inst.state);
for (var i = replace ? 1 : 0; i < queue.length; i++) {
var partial = queue[i];
_assign(nextState, typeof partial === 'function' ? partial.call(inst, nextState, props, context) : partial);
}
return nextState;
},
우 리 는 아래 코드 에 만 관심 을 가 져 야 한다.
_assign(nextState, typeof partial === 'function' ? partial.call(inst, nextState, props, context) : partial);
대상 이 들 어 오 면 한 번 으로 합 쳐 지 는 것 이 분명 하 다.
Object.assign(
nextState,
{index: state.index+ 1},
{index: state.index+ 1}
)
함수 가 들 어 오 면 함수 의 인자 preState 는 지난번 합병 후의 결과 이기 때문에 계산 결 과 는 정확 합 니 다.
4.
state
호출 componentDidMount
componentDid Mount () 에서 setState () 를 즉시 호출 할 수 있 습 니 다.추가 렌 더 링 을 실행 하지만 브 라 우 저 에서 화면 을 새로 고치 기 전에 발생 합 니 다.이 경우 render () 가 두 번 호출 되 더 라 도 사용자 가 중간 상 태 를 보지 못 하도록 보장 합 니 다.성능 문 제 를 일 으 키 기 때문에 이 모델 을 신중하게 사용 하 세 요.대부분의 경우 constructor () 에서 할당 초기 상 태 를 사용 하여 대체 할 수 있 습 니 다.그러나 어떤 경우 에는 반드시 이렇게 해 야 한다. 예 를 들 어 모드 상자 와 도구 알림 상자 등 이다.이때, 당신 은 먼저 이 DOM 노드 를 측정 해야만 사이즈 나 위치 에 의존 하 는 어떤 것들 을 과장 할 수 있 습 니 다.이상 은 공식 문서 의 설명 입 니 다.
setstate
에서 직접 호출 componentDidMount
하 는 것 을 추천 하지 않 습 니 다. 위의 분석 에 따 르 면 setState
자체 가 한 번 의 업데이트 에 있 고 우 리 는 한 번 componentDidMount
을 호출 하면 미래 에 다시 한 번 setState
을 진행 하여 필요 하지 않 은 성능 낭 비 를 초래 하고 대부분 상황 은 초기 값 을 설정 하여 해결 할 수 있 습 니 다.물론
render
우 리 는 인 터 페 이 스 를 호출 하고 리 셋 에서 수정 할 수 있다 componentDidMount
. 이것 은 정확 한 방법 이다.state 초기 값 이 dom 속성 에 의존 할 때
state
에서 componentDidMount
피 할 수 없습니다.5.
setState
componentWillUpdate
이 두 생명 주기 중 에는 호출 할 수 없다
componentDidUpdate
.위의 흐름 도 에서 쉽게 발견 할 수 있 는데, 그 안에서 호출
setState
하면 사 순환 을 일 으 켜 프로그램 이 붕 괴 될 수 있다.6. 추천 사용법
호출
setState
시 함수 전달 setState
값 을 사용 하여 리 셋 함수 에서 최신 업 데 이 트 된 state
값 을 가 져 옵 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JAVA- 소스 코드 분할(Package 사용)▪️test45.java 소스 코드 ▪️test47.java 소스 코드 ▪️실행 결과 더하면 12, 당기면 8 ▪️예① 클래스 이름에 대한 완전한 입력 생략 import 문 사용 ▪️예① test45.java 소스 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.