Merge pull request #17 from Kartvya69/fix/tui-freeze-style-rerender

Fix TUI freeze without dropping prompt styles
This commit is contained in:
Kevin Codex
2026-04-01 19:54:12 +08:00
committed by GitHub
2 changed files with 33 additions and 12 deletions

View File

@@ -265,13 +265,14 @@ export const setAttribute = (
markDirty(node) markDirty(node)
} }
export const setStyle = (node: DOMNode, style: Styles): void => { export const setStyle = (node: DOMNode, style: Styles | undefined): void => {
const nextStyle = style ?? {}
// Compare style properties to avoid marking dirty unnecessarily. // Compare style properties to avoid marking dirty unnecessarily.
// React creates new style objects on every render even when unchanged. // React creates new style objects on every render even when unchanged.
if (stylesEqual(node.style, style)) { if (stylesEqual(node.style, nextStyle)) {
return return
} }
node.style = style node.style = nextStyle
markDirty(node) markDirty(node)
} }

View File

@@ -59,6 +59,12 @@ $ npm install --save-dev react-devtools-core
type AnyObject = Record<string, unknown> type AnyObject = Record<string, unknown>
type UpdatePayload = {
props?: AnyObject
style?: AnyObject
nextStyle?: Styles | undefined
}
const diff = (before: AnyObject, after: AnyObject): AnyObject | undefined => { const diff = (before: AnyObject, after: AnyObject): AnyObject | undefined => {
if (before === after) { if (before === after) {
return return
@@ -232,7 +238,7 @@ const reconciler = createReconciler<
unknown, unknown,
DOMElement, DOMElement,
HostContext, HostContext,
boolean, UpdatePayload | null,
NodeJS.Timeout, NodeJS.Timeout,
-1, -1,
null null
@@ -403,8 +409,19 @@ const reconciler = createReconciler<
_type: ElementNames, _type: ElementNames,
oldProps: Props, oldProps: Props,
newProps: Props, newProps: Props,
): boolean { ): UpdatePayload | null {
return oldProps !== newProps const props = diff(oldProps, newProps)
const style = diff(oldProps['style'] as Styles, newProps['style'] as Styles)
if (!props && !style) {
return null
}
return {
props,
style,
nextStyle: newProps['style'] as Styles | undefined,
}
}, },
commitMount(node: DOMElement): void { commitMount(node: DOMElement): void {
getFocusManager(node).handleAutoFocus(node) getFocusManager(node).handleAutoFocus(node)
@@ -432,13 +449,16 @@ const reconciler = createReconciler<
}, },
commitUpdate( commitUpdate(
node: DOMElement, node: DOMElement,
_updatePayload: boolean, updatePayload: UpdatePayload | null,
_type: ElementNames, _type: ElementNames,
oldProps: Props, _oldProps: Props,
newProps: Props, _newProps: Props,
): void { ): void {
const props = diff(oldProps, newProps) if (!updatePayload) {
const style = diff(oldProps['style'] as Styles, newProps['style'] as Styles) return
}
const { props, style, nextStyle } = updatePayload
if (props) { if (props) {
for (const [key, value] of Object.entries(props)) { for (const [key, value] of Object.entries(props)) {
@@ -462,7 +482,7 @@ const reconciler = createReconciler<
} }
if (style && node.yogaNode) { if (style && node.yogaNode) {
applyStyles(node.yogaNode, style, newProps['style'] as Styles) applyStyles(node.yogaNode, style, nextStyle)
} }
}, },
commitTextUpdate(node: TextNode, _oldText: string, newText: string): void { commitTextUpdate(node: TextNode, _oldText: string, newText: string): void {