mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-17 03:57:18 +00:00
fix(deps,cli): add @types/react overrides + move refreshStatic out of setCurrentModel updater
Two follow-ups from the multi-round audit of the ink 7.0.3 re-upgrade: 1. @types/react / @types/react-dom now pinned to ^19.2.0 in root overrides. packages/web-templates still declares @types/react ^18.2.0 in its devDeps. Today the CLI build is unaffected (web-templates's 18.x types are nested in its own node_modules and the React-using src/insight and src/export-html files are excluded from its tsconfig build), but a future reincludes-or-hoist accident would land conflicting global JSX namespaces in the CLI compile graph. Match the dep dedup we already enforce for `react` and `react-dom` so the type graph stays as deduped as the runtime graph. 2. AppContainer's onModelChange handler was calling refreshStatic() as a side-effect inside the setCurrentModel updater. React.StrictMode double-invokes state updaters in dev, so model swaps fired two clearTerminal writes + two <Static> key bumps. The double work was masked under ink 6 (key changes were no-ops on <Static>), but ink 7.0.3 honors key changes — the doubled work is now potentially visible as a faster flash-flash on every model switch. Refactor: setCurrentModel becomes a pure setter; refreshStatic moves into a useEffect keyed on currentModel with a ref-comparison guard so the first render doesn't fire. Single clearTerminal write per real model change, even under StrictMode. Verified: npm ls ink → single 7.0.3, npm ls react → single 19.2.4, npm ls @types/react → 19.2.10 hoisted (npm flags web-templates's 18.x constraint as overridden, which is the intended behavior). Typecheck clean across cli + core workspaces.
This commit is contained in:
parent
5bb49d945d
commit
b25831b0ed
2 changed files with 18 additions and 10 deletions
|
|
@ -81,7 +81,9 @@
|
|||
"baseline-browser-mapping": "^2.9.19",
|
||||
"normalize-package-data": "^7.0.1",
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4"
|
||||
"react-dom": "^19.2.4",
|
||||
"@types/react": "^19.2.0",
|
||||
"@types/react-dom": "^19.2.0"
|
||||
},
|
||||
"bin": {
|
||||
"qwen": "dist/cli.js"
|
||||
|
|
|
|||
|
|
@ -591,19 +591,25 @@ export const AppContainer = (props: AppContainerProps) => {
|
|||
// Keep the static header in sync with model changes without polling.
|
||||
// Ink's <Static> output is append-only, so model changes must explicitly
|
||||
// clear and remount the static region to redraw the banner at the top.
|
||||
//
|
||||
// refreshStatic() is fired from an effect (not inside the setState updater)
|
||||
// so React.StrictMode's double-invoke of state updaters doesn't translate
|
||||
// into two clearTerminal writes per model change. Side-effects belong in
|
||||
// effects; the updater stays pure.
|
||||
useEffect(() => {
|
||||
const unsubscribe = config.onModelChange((model) => {
|
||||
setCurrentModel((prev) => {
|
||||
if (prev === model) {
|
||||
return prev;
|
||||
}
|
||||
refreshStatic();
|
||||
return model;
|
||||
});
|
||||
setCurrentModel(model);
|
||||
});
|
||||
|
||||
return unsubscribe;
|
||||
}, [config, refreshStatic]);
|
||||
}, [config]);
|
||||
|
||||
const prevCurrentModelRef = useRef(currentModel);
|
||||
useEffect(() => {
|
||||
if (prevCurrentModelRef.current !== currentModel) {
|
||||
prevCurrentModelRef.current = currentModel;
|
||||
refreshStatic();
|
||||
}
|
||||
}, [currentModel, refreshStatic]);
|
||||
|
||||
const {
|
||||
isThemeDialogOpen,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue