fix: stabilize NoteEditor/NoteEditorPane memoization with useCallback
Root cause: inline arrow functions for onDelete and onSave props created new references every render, breaking React.memo and causing editor re-renders that steal focus.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { useState, useRef, useEffect, memo } from "react";
|
import { useState, useRef, useEffect, memo, useCallback } from "react";
|
||||||
import { createRoute } from "@tanstack/react-router";
|
import { createRoute } from "@tanstack/react-router";
|
||||||
import { Route as appRoute } from "../_app";
|
import { Route as appRoute } from "../_app";
|
||||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||||
@@ -90,6 +90,10 @@ const NoteEditorPane = memo(function NoteEditorPane({ note, onDelete }: { note:
|
|||||||
onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["notes"] }); },
|
onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["notes"] }); },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleSave = useCallback((html: string) => {
|
||||||
|
updateMutation.mutate({ id: note.id, data: { content: html } });
|
||||||
|
}, [note.id, updateMutation]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="flex items-center gap-2 p-3 border-b">
|
<div className="flex items-center gap-2 p-3 border-b">
|
||||||
@@ -121,7 +125,7 @@ const NoteEditorPane = memo(function NoteEditorPane({ note, onDelete }: { note:
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 overflow-auto">
|
<div className="flex-1 overflow-auto">
|
||||||
<NoteEditor key={note.id} initialContent={note.content || ''} onSave={(html) => { updateMutation.mutate({ id: note.id, data: { content: html } }); }} />
|
<NoteEditor key={note.id} initialContent={note.content || ''} onSave={handleSave} />
|
||||||
</div>
|
</div>
|
||||||
{/* Backlinks section */}
|
{/* Backlinks section */}
|
||||||
{showBacklinks && note.backlinks && note.backlinks.length > 0 && (
|
{showBacklinks && note.backlinks && note.backlinks.length > 0 && (
|
||||||
@@ -192,6 +196,10 @@ function NotesPage() {
|
|||||||
|
|
||||||
const selectedNote = selectedNoteRef.current;
|
const selectedNote = selectedNoteRef.current;
|
||||||
|
|
||||||
|
const handleDeleteNote = useCallback((id: string) => {
|
||||||
|
deleteMutation.mutate(id);
|
||||||
|
}, [deleteMutation]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-[calc(100vh-8rem)] -m-4 md:-m-6">
|
<div className="flex h-[calc(100vh-8rem)] -m-4 md:-m-6">
|
||||||
{/* Left pane - note list */}
|
{/* Left pane - note list */}
|
||||||
@@ -240,7 +248,7 @@ function NotesPage() {
|
|||||||
{/* Right pane - editor (memoized, won't re-render on parent state changes) */}
|
{/* Right pane - editor (memoized, won't re-render on parent state changes) */}
|
||||||
<div className="flex-1 flex flex-col">
|
<div className="flex-1 flex flex-col">
|
||||||
{selectedNote ? (
|
{selectedNote ? (
|
||||||
<NoteEditorPane key={selectedNote.id} note={selectedNote} onDelete={(id) => deleteMutation.mutate(id)} />
|
<NoteEditorPane key={selectedNote.id} note={selectedNote} onDelete={handleDeleteNote} />
|
||||||
) : (
|
) : (
|
||||||
<div className="flex items-center justify-center flex-1 text-muted-foreground">
|
<div className="flex items-center justify-center flex-1 text-muted-foreground">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
|
|||||||
Reference in New Issue
Block a user