Fix gRPC autocomplete schema not being applied

Two issues fixed:

1. Initialize stateExtensions with empty object {} instead of undefined.
   When called with no argument, the schema state was undefined, causing
   jsonCompletion() to return [] instead of a proper result object, which
   CodeMirror's autocomplete didn't handle correctly.

2. Change editorView from useRef to useState so the effect that calls
   updateSchema() properly re-runs when the editor view is set. With useRef,
   the effect could run before the editor was mounted or with a stale
   reference when the editor was recreated.
This commit is contained in:
Gregory Schier
2026-01-10 14:57:15 -08:00
parent 4d75b8ef06
commit 2b43407ddf

View File

@@ -10,7 +10,7 @@ import {
stateExtensions, stateExtensions,
updateSchema, updateSchema,
} from 'codemirror-json-schema'; } from 'codemirror-json-schema';
import { useCallback, useEffect, useMemo, useRef } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react';
import type { ReflectResponseService } from '../hooks/useGrpc'; import type { ReflectResponseService } from '../hooks/useGrpc';
import { showAlert } from '../lib/alert'; import { showAlert } from '../lib/alert';
import { showDialog } from '../lib/dialog'; import { showDialog } from '../lib/dialog';
@@ -39,15 +39,15 @@ export function GrpcEditor({
protoFiles, protoFiles,
...extraEditorProps ...extraEditorProps
}: Props) { }: Props) {
const editorViewRef = useRef<EditorView>(null); const [editorView, setEditorView] = useState<EditorView | null>(null);
const handleInitEditorViewRef = useCallback((h: EditorView | null) => { const handleInitEditorViewRef = useCallback((h: EditorView | null) => {
editorViewRef.current = h; setEditorView(h);
}, []); }, []);
// Find the schema for the selected service and method and update the editor // Find the schema for the selected service and method and update the editor
useEffect(() => { useEffect(() => {
if ( if (
editorViewRef.current == null || editorView == null ||
services === null || services === null ||
request.service === null || request.service === null ||
request.method === null request.method === null
@@ -91,7 +91,7 @@ export function GrpcEditor({
} }
try { try {
updateSchema(editorViewRef.current, JSON.parse(schema)); updateSchema(editorView, JSON.parse(schema));
} catch (err) { } catch (err) {
showAlert({ showAlert({
id: 'grpc-parse-schema-error', id: 'grpc-parse-schema-error',
@@ -107,7 +107,7 @@ export function GrpcEditor({
), ),
}); });
} }
}, [services, request.method, request.service]); }, [editorView, services, request.method, request.service]);
const extraExtensions = useMemo( const extraExtensions = useMemo(
() => [ () => [
@@ -118,7 +118,7 @@ export function GrpcEditor({
jsonLanguage.data.of({ jsonLanguage.data.of({
autocomplete: jsonCompletion(), autocomplete: jsonCompletion(),
}), }),
stateExtensions(/** Init with empty schema **/), stateExtensions({}),
], ],
[], [],
); );