Skip to content

Commit 7637bff

Browse files
authoredFeb 9, 2023
fix: Fix echo onChange call when value prop is changed (#456)
1 parent 075531a commit 7637bff

File tree

2 files changed

+18
-2
lines changed

2 files changed

+18
-2
lines changed
 

‎core/src/__tests__/index.test.tsx

+7
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,10 @@ it('CodeMirror editable', async () => {
8585
expect(text.className).toEqual('cm-content');
8686
expect(text.tagName).toEqual('DIV');
8787
});
88+
89+
it("CodeMirror doesn't echo changes", async () => {
90+
const handleChange = jest.fn();
91+
const { rerender } = render(<CodeMirror value="value a" onChange={handleChange} />);
92+
rerender(<CodeMirror value="value b" onChange={handleChange} />);
93+
expect(handleChange).not.toHaveBeenCalled();
94+
});

‎core/src/useCodeMirror.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { useEffect, useState } from 'react';
2-
import { EditorState, StateEffect } from '@codemirror/state';
2+
import { Annotation, EditorState, StateEffect } from '@codemirror/state';
33
import { indentWithTab } from '@codemirror/commands';
44
import { EditorView, keymap, ViewUpdate, placeholder } from '@codemirror/view';
55
import { basicSetup } from '@uiw/codemirror-extensions-basic-setup';
66
import { oneDark } from '@codemirror/theme-one-dark';
77
import { getStatistics } from './utils';
88
import { ReactCodeMirrorProps } from '.';
99

10+
const External = Annotation.define<boolean>();
11+
1012
export interface UseCodeMirror extends ReactCodeMirrorProps {
1113
container?: HTMLDivElement | null;
1214
}
@@ -60,7 +62,13 @@ export function useCodeMirror(props: UseCodeMirror) {
6062
},
6163
});
6264
const updateListener = EditorView.updateListener.of((vu: ViewUpdate) => {
63-
if (vu.docChanged && typeof onChange === 'function') {
65+
if (
66+
vu.docChanged &&
67+
typeof onChange === 'function' &&
68+
// Fix echoing of the remote changes:
69+
// If transaction is market as remote we don't have to call `onChange` handler again
70+
!vu.transactions.some((tr) => tr.annotation(External))
71+
) {
6472
const doc = vu.state.doc;
6573
const value = doc.toString();
6674
onChange(value, vu);
@@ -188,6 +196,7 @@ export function useCodeMirror(props: UseCodeMirror) {
188196
if (view && value !== currentValue) {
189197
view.dispatch({
190198
changes: { from: 0, to: currentValue.length, insert: value || '' },
199+
annotations: [External.of(true)],
191200
});
192201
}
193202
}, [value, view]);

0 commit comments

Comments
 (0)
Please sign in to comment.