[Perf] Teact: Avoid redundant renders when updating state with a callback
This commit is contained in:
parent
6213ed60d5
commit
c6bd762a4c
@ -473,39 +473,41 @@ export function useState<T>(initial?: T, debugKey?: string): [T, StateHookSetter
|
|||||||
value: initial,
|
value: initial,
|
||||||
nextValue: initial,
|
nextValue: initial,
|
||||||
setter: ((componentInstance) => (newValue: ((current: T) => T) | T) => {
|
setter: ((componentInstance) => (newValue: ((current: T) => T) | T) => {
|
||||||
if (byCursor[cursor].nextValue !== newValue) {
|
if (typeof newValue === 'function') {
|
||||||
byCursor[cursor].nextValue = typeof newValue === 'function'
|
newValue = (newValue as (current: T) => T)(byCursor[cursor].value);
|
||||||
? (newValue as (current: T) => T)(byCursor[cursor].value)
|
}
|
||||||
: newValue;
|
|
||||||
|
|
||||||
if (!componentInstance.prepareForFrame || !componentInstance.forceUpdate) {
|
if (byCursor[cursor].nextValue === newValue) {
|
||||||
componentInstance.prepareForFrame = throttleWithPrimaryRaf(
|
return;
|
||||||
() => prepareComponentForFrame(componentInstance),
|
}
|
||||||
|
|
||||||
|
byCursor[cursor].nextValue = newValue;
|
||||||
|
|
||||||
|
if (!componentInstance.prepareForFrame || !componentInstance.forceUpdate) {
|
||||||
|
componentInstance.prepareForFrame = throttleWithPrimaryRaf(
|
||||||
|
() => prepareComponentForFrame(componentInstance),
|
||||||
|
);
|
||||||
|
componentInstance.forceUpdate = throttleWithRaf(
|
||||||
|
() => forceUpdateComponent(componentInstance),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentInstance.prepareForFrame();
|
||||||
|
componentInstance.forceUpdate();
|
||||||
|
|
||||||
|
if (DEBUG_MORE) {
|
||||||
|
if (componentInstance.name !== 'TeactNContainer') {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(
|
||||||
|
'[Teact.useState]',
|
||||||
|
componentInstance.name,
|
||||||
|
// `componentInstance.Component` may be set to `null` by GC helper
|
||||||
|
componentInstance.Component && (componentInstance.Component as FC_withDebug).DEBUG_contentComponentName
|
||||||
|
? `> ${(componentInstance.Component as FC_withDebug).DEBUG_contentComponentName}`
|
||||||
|
: '',
|
||||||
|
`State update at cursor #${cursor}${debugKey ? ` (${debugKey})` : ''}, next value: `,
|
||||||
|
byCursor[cursor].nextValue,
|
||||||
);
|
);
|
||||||
componentInstance.forceUpdate = throttleWithRaf(
|
|
||||||
() => forceUpdateComponent(componentInstance),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentInstance.prepareForFrame();
|
|
||||||
componentInstance.forceUpdate();
|
|
||||||
|
|
||||||
if (DEBUG_MORE) {
|
|
||||||
if (componentInstance.name !== 'TeactNContainer') {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log(
|
|
||||||
'[Teact.useState]',
|
|
||||||
componentInstance.name,
|
|
||||||
// `componentInstance.Component` may be set to `null` by GC helper
|
|
||||||
componentInstance.Component && (componentInstance.Component as FC_withDebug).DEBUG_contentComponentName
|
|
||||||
? `> ${(componentInstance.Component as FC_withDebug).DEBUG_contentComponentName}`
|
|
||||||
: '',
|
|
||||||
debugKey
|
|
||||||
? `State update for ${debugKey}, next value: `
|
|
||||||
: `State update at cursor #${cursor}, next value: `,
|
|
||||||
byCursor[cursor].nextValue,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})(renderingInstance),
|
})(renderingInstance),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user