Skip to content

Commit f3ff3fc

Browse files
committed
FIX: React error #185 hydration mismatch in SlateEditor and RelatedPages
ISSUE: React error #185 still occurring when visiting pages ROOT CAUSE: Hydration mismatches in array rendering and content processing FIXES: ✅ Added client-side rendering check to SlateEditor to prevent hydration mismatches ✅ Added safety checks for content processing in contentToSlate function ✅ Added Array.isArray() checks in RelatedPagesSection for candidates and relatedPages ✅ Added proper null/undefined checks for node and child objects ✅ Added loading state for SlateEditor during SSR/client transition EXPECTED RESULTS: - No more React error #185 when visiting pages - Smooth client-side rendering without hydration mismatches - Proper error handling for malformed content
1 parent 1b2d1d9 commit f3ff3fc

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

app/components/editor/SlateEditor.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ const contentToSlate = (content: any[]): Descendant[] => {
103103
return content.map((node, index) => {
104104
console.log(`🔍 contentToSlate: Processing node ${index}:`, { node, type: typeof node });
105105

106+
// Safety check to prevent hydration mismatches
107+
if (!node || typeof node !== 'object') {
108+
console.warn(`🔍 contentToSlate: Invalid node at index ${index}, creating default paragraph`);
109+
return { type: 'paragraph', children: [{ text: '' }] };
110+
}
111+
106112
if (node.type === 'paragraph') {
107113
const children: Descendant[] = [];
108114

@@ -111,6 +117,12 @@ const contentToSlate = (content: any[]): Descendant[] => {
111117
node.children.forEach((child: any, childIndex: number) => {
112118
console.log(`🔍 contentToSlate: Processing child ${childIndex}:`, { child });
113119

120+
// Safety check for child objects
121+
if (!child || typeof child !== 'object') {
122+
console.warn(`🔍 contentToSlate: Invalid child at index ${childIndex}, skipping`);
123+
return;
124+
}
125+
114126
if (child.type === 'link') {
115127
children.push({
116128
type: 'link',
@@ -268,6 +280,12 @@ const SlateEditor: React.FC<SlateEditorProps> = ({
268280
showToolbar = true,
269281
onInsertLinkRequest
270282
}) => {
283+
// Prevent hydration mismatches by ensuring client-side rendering
284+
const [isClient, setIsClient] = useState(false);
285+
286+
useEffect(() => {
287+
setIsClient(true);
288+
}, []);
271289
const editor = useMemo(() => createSlateEditor(), []);
272290
// Create safe initial value for Slate
273291
const safeInitialValue = useMemo(() => {
@@ -662,6 +680,17 @@ const SlateEditor: React.FC<SlateEditorProps> = ({
662680
}
663681
}, [onInsertLinkRequest]);
664682

683+
// Prevent hydration mismatches by only rendering on client
684+
if (!isClient) {
685+
return (
686+
<div className="slate-editor-container w-full">
687+
<div className="p-4 text-center text-muted-foreground">
688+
Loading editor...
689+
</div>
690+
</div>
691+
);
692+
}
693+
665694
return (
666695
<div className="slate-editor-container w-full">
667696
{showToolbar && (

app/components/features/RelatedPagesSection.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ const getRelatedPagesAsync = async (pageId: string, pageTitle: string, pageConte
6060
});
6161

6262
// Score candidates based on word overlap
63-
const scoredCandidates = candidates.map(candidate => {
63+
const scoredCandidates = Array.isArray(candidates) ? candidates.map(candidate => {
6464
const candidateTitle = candidate.title || '';
6565
const candidateContent = candidate.content || '';
6666

@@ -79,7 +79,7 @@ const getRelatedPagesAsync = async (pageId: string, pageTitle: string, pageConte
7979
similarity: Math.min(score / Math.max(allWords.length, 1), 1),
8080
score
8181
};
82-
});
82+
}) : [];
8383

8484
return scoredCandidates
8585
.filter(candidate => candidate.score > 0)
@@ -199,7 +199,7 @@ export default function RelatedPagesSection({ page, linkedPageIds = [] }: Relate
199199
<Loader2 className="h-3 w-3 animate-spin" />
200200
<span>Loading related pages by others...</span>
201201
</div>
202-
) : relatedPages.length > 0 ? (
202+
) : Array.isArray(relatedPages) && relatedPages.length > 0 ? (
203203
<div className="flex flex-wrap gap-2">
204204
{relatedPages.map((relatedPage, index) => (
205205
<div key={relatedPage.id} className="flex items-center">

0 commit comments

Comments
 (0)