this.update.enqueueSetState 통해서 Update를 생성하고 실행한다.
Update 활성화
|
v
shared.pending 생성
|
v
....
|
v
updateQueue 처리(completeWork)
|
v
...// ClassComponent, HostRoot
const update = {
eventTime: "",
lane: "",
suspenseConfig: "",
tag: UpdateState, // CaptureUpdate, ForceUpdate, ReplaceState, UpdateState
payload: null, // ClassComponent this.setState args[0], HostRoot ReactDOM.render args[0]
callback: null, // ClassComponent this.setState args[1], HostRoot ReactDOM.render args[2]
next: null,
};
// FunctionComponent
const update = {
eventTime: "",
lane: "",
suspenseConfig: "",
action: "", // ????
eagerReducer: null, // useState는 basicStateReducer사용.
eagerState: null, // 리듀서를 통해 action의 결과값을 얻는다. basicStateReducer(baseState, action)
next: null,
};
function basicStateReducer(state, action) {
return typeof action === "function" ? action(state) : action;
}// ClassComponent
const Fiber = {
updateQueue: {
baseState: '',
firstBaseUpdate: Update,
lastBaseUpdate: Update,
shared: {
pending: Updates
}
effects: [] // update.callback 이 존재하는 경우만 배열에 추가
}
memoizedState: stateValue
}
// FunctionComponent
const Fiber = {
memoizedState: { // Hook
memoizedState: stateValue,
baseState: '',
baseQueue: Update,
queue: Updates,
next, // Hook list
}
}const App = () => {
const [count, setCount] = useState(0);
const onClick = () => setCount(count + 1);
return <div onClick={onClick}>{count}</div>;
};const App = () => {
const [count, setCount] = useState(0);
const onClick1 = () => {
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
};
const onClick2 = () => {
setCount((baseState) => baseState + 1);
setCount((baseState) => baseState + 1);
setCount(count + 1);
setCount((baseState) => baseState + 1);
};
const onClick3 = () => {
setTimeout(() => {
// concurrent mode일 경우 배치됨, legacy mode일 경우 3번 랜딩됨.
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
}, 0);
};
return (
<>
<h1>{count}</h1>
<div onClick={onClick1}>click1</div>
<div onClick={onClick2}>click2</div>
<div onClick={onClick3}>click3</div>
</>
);
};const arr = [];
arr.length = 6000;
arr.fill(0);
const App = () => {
const btnRef = useRef(null);
const [count, setCount] = useState(0);
const onClick = () => {
setCount((count) => count + 1);
};
useEffect(() => {
// 레거시 모드에서는 10, 11로 화면에 노출
// 동시성 모드에서는 1, 11로 화면에 노출(1차 우선순위 높은거 실행, 2차 순차적으로 실행.)
// [10_2, x+1_1]
setTimeout(() => {
setCount(count + 10);
}, 2000);
setTimeout(() => {
btnRef.current.click();
}, 2000);
}, []);
return (
<>
<h1>{count}</h1>
<div
onClick={onClick}
ref={btnRef}
>
click1
</div>
{arr.map(() => (
<div>{count}</div>
))}
</>
);
};// For example:
//
// Given a base state of '', and the following queue of updates
//
// A1 - B2 - C1 - D2
//
// where the number indicates the priority, and the update is applied to the
// previous state by appending a letter, React will process these updates as
// two separate renders, one per distinct priority level:
//
// First render, at priority 1:
// Base state: ''
// Updates: [A1, C1]
// Result state: 'AC'
//
// Second render, at priority 2:
// Base state: 'A' <- The base state does not include C1,
// because B2 was skipped.
// Updates: [B2, C1, D2] <- C1 was rebased on top of B2
// Result state: 'ABCD'