chore: stabilize React context values and callback references to prev…#277
Merged
chore: stabilize React context values and callback references to prev…#277
Conversation
Reviewer's GuideRefactors multiple React components and providers to stabilize context values, event handlers, and callback references using useMemo/useCallback, reduce inline closures, and improve scroll/event handling to avoid unnecessary re-renders and side-effects across chat, database, calendar, and app overlay features. Class diagram for stabilized AI assistant contexts and view loadingclassDiagram
class AIAssistantProvider {
-children ReactNode
-request RequestInstance
-viewId string
-selectedModelName string
-isFetching boolean
-isApplying boolean
-applyingState any
-assistantType string
-placeholderContent string
-comment string
-responseMode string
-responseFormat string
-isGlobalDocument boolean
-error Error
-scrollContainer HTMLElement
-openDiscard boolean
-completionHistoryRef CompletionItem[]
+hasAIAnswer() boolean
+handleKeyDown(event KeyboardEvent)
+handleCloseDiscard() void
}
class ModelRequestInstance {
+getModelList() Promise~Model[]~
+getCurrentModel() Promise~string~
+setCurrentModel(modelName string) Promise~void~
}
class ModelSelectorValue {
+selectedModelName string
+setSelectedModelName(name string) void
+requestInstance ModelRequestInstance
}
class WriterContextValue {
+viewId string
+fetchViews() Promise~View[]~
+placeholderContent string
+comment string
+improveWriting() void
+assistantType string
+isFetching boolean
+isApplying boolean
+askAIAnything() void
+continueWriting() void
+explain() void
+fixSpelling() void
+makeLonger() void
+makeShorter() void
+askAIAnythingWithRequest() void
+setOpenDiscard(open boolean) void
+applyingState any
+setRagIds(ids string[]) void
+exit() void
+setEditorData(data any) void
+keep() void
+accept() void
+rewrite() void
+stop() void
+responseMode string
+setResponseMode(mode string) void
+responseFormat string
+setResponseFormat(format string) void
+isGlobalDocument boolean
+error Error
+scrollContainer HTMLElement
+hasAIAnswer() boolean
+selectedModelName string
+setSelectedModelName(name string) void
}
class ViewLoaderProvider {
+getView(viewId string) Promise~View~
+fetchViews() Promise~View[]~
}
AIAssistantProvider o--> ModelRequestInstance : creates
AIAssistantProvider o--> ModelSelectorValue : memoized
AIAssistantProvider o--> WriterContextValue : memoized
AIAssistantProvider o--> ViewLoaderProvider : configures
ModelSelectorValue ..> ModelRequestInstance : uses
WriterContextValue ..> ModelRequestInstance : uses request.fetchViews
Class diagram for stabilized chat and prompt modal providersclassDiagram
class Main {
-workspaceId string
-chatId string
-requestInstance ChatRequestInstance
-currentUser User
-openingViewId string
-selectionMode boolean
-loadDatabasePrompts LoadDatabasePrompts
-testDatabasePromptConfig TestDatabasePromptConfig
+getView(viewId string, forceRefresh boolean) Promise~View~
+fetchViews(forceRefresh boolean) Promise~View[]~
}
class ChatContextValue {
+workspaceId string
+chatId string
+requestInstance ChatRequestInstance
+currentUser User
+openingViewId string
+onOpenView(viewId string) void
+onCloseView() void
+selectionMode boolean
+onOpenSelectionMode() void
+onCloseSelectionMode() void
+loadDatabasePrompts LoadDatabasePrompts
+testDatabasePromptConfig TestDatabasePromptConfig
}
class ChatContentWithModelSync {
+currentUser User
+selectionMode boolean
}
class ChatModelRequestInstance {
+getModelList() Promise~Model[]~
+getCurrentModel() Promise~string~
+setCurrentModel(modelName string) Promise~void~
}
class ChatModelSelectorValue {
+selectedModelName string
+setSelectedModelName(name string) void
+requestInstance ChatModelRequestInstance
+chatId string
}
class PromptModalProvider {
-workspaceId string
-loadDatabasePrompts LoadDatabasePrompts
-testDatabasePromptConfig TestDatabasePromptConfig
-isOpen boolean
-currentPromptId string
-prompts AiPrompt[]
-currentDatabaseConfig PromptDatabaseConfiguration
-fields PromptDatabaseField[]
+openModal() void
+closeModal() void
+saveDatabaseConfig(config PromptDatabaseConfiguration) Promise~void~
+reloadDatabasePrompts() Promise~void~
}
class PromptModalContextValue {
+isOpen boolean
+currentPromptId string
+updateCurrentPromptId(id string) void
+prompts AiPrompt[]
+openModal() void
+closeModal() void
+databaseConfig PromptDatabaseConfiguration
+fields PromptDatabaseField[]
+testDatabasePromptConfig TestDatabasePromptConfig
+saveDatabaseConfig(config PromptDatabaseConfiguration) Promise~void~
+reloadDatabasePrompts() Promise~void~
}
class BuiltInPromptLoader {
+getBuiltInPrompts() AiPrompt[]
}
Main o--> ChatContextValue : memoized
Main o--> PromptModalProvider : renders
Main o--> ViewLoaderProvider : configures
ChatContentWithModelSync o--> ChatModelRequestInstance : memoized
ChatContentWithModelSync o--> ChatModelSelectorValue : memoized
PromptModalProvider o--> PromptModalContextValue : memoized
PromptModalProvider ..> BuiltInPromptLoader : uses getBuiltInPrompts
Flow diagram for scroll detection hook with debounced button visibilityflowchart TD
A[start useScrollDetection] --> B[resolve scrollElement from containerRef or getScrollParent]
B --> C{scrollElement exists?}
C -- no --> Z[end]
C -- yes --> D[define handleScroll]
D --> E[on scroll: set button opacity 0 and pointer-events none]
E --> F{existing showTimeoutRef?}
F -- yes --> G[clearTimeout showTimeoutRef]
F -- no --> H[skip]
G --> I[start new timeout 1000ms]
H --> I
I --> J[after 1000ms: set button opacity 1 and pointer-events auto]
J --> K[reset showTimeoutRef to null]
K --> L[add scroll listener with passive true]
L --> M[cleanup effect]
M --> N{showTimeoutRef not null?}
N -- yes --> O[clearTimeout and reset showTimeoutRef]
N -- no --> P[skip]
O --> Q[remove scroll listener with same options]
P --> Q
Q --> Z[end]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
…ent unnecessary re-renders
07f3573 to
b6762d5
Compare
- preserve first-message chat renames and stable model reads - guard async chat settings and notification updates after unmount - fix board/grid scroll listener cleanup and align toolbar fallback - add cypress stability coverage for chat, database, editor, and image toolbar flows
- replace legacy AppContext access with auth/navigation/outline/operations/sync hooks - make optional auth and workspace dependencies explicit at call sites - split board selection state from board actions - update Storybook and modal/view wiring for the new context boundaries
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…ent unnecessary re-renders
Description
Checklist
General
Testing
Feature-Specific
Summary by Sourcery
Stabilize React context values, callbacks, and scroll handlers across chat, database, editor, and app overlay components to reduce unnecessary re-renders and improve UI responsiveness.
Enhancements: