Skip to content

Commit 48a754b

Browse files
committed
fix(merge): fix onChange props issue. #681
1 parent a7137dc commit 48a754b

File tree

4 files changed

+51
-48
lines changed

4 files changed

+51
-48
lines changed

merge/src/Internal.tsx

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import React, { useEffect, useImperativeHandle, useRef } from 'react';
2-
import { EditorStateConfig, StateEffect } from '@codemirror/state';
2+
import { EditorStateConfig } from '@codemirror/state';
33
import { getDefaultExtensions } from '@uiw/react-codemirror';
44
import { MergeView, MergeConfig, DirectMergeConfig } from '@codemirror/merge';
55
import { useStore } from './store';
66
import { CodeMirrorMergeProps } from './';
7-
7+
import { EditorView, ViewUpdate } from '@codemirror/view';
88
export interface InternalRef {
99
container?: HTMLDivElement | null;
1010
view?: MergeView;
@@ -48,28 +48,46 @@ export const Internal = React.forwardRef<InternalRef, CodeMirrorMergeProps>((pro
4848
[editor, view, modified, original, opts],
4949
);
5050

51+
const originalUpdateListener = EditorView.updateListener.of((vu: ViewUpdate) => {
52+
if (vu.docChanged && typeof originalExtension?.onChange === 'function') {
53+
const doc = vu.state.doc;
54+
const val = doc.toString();
55+
originalExtension?.onChange(val, vu);
56+
}
57+
});
58+
59+
const modifiedUpdateListener = EditorView.updateListener.of((vu: ViewUpdate) => {
60+
if (vu.docChanged && typeof modifiedExtension?.onChange === 'function') {
61+
const doc = vu.state.doc;
62+
const val = doc.toString();
63+
modifiedExtension?.onChange(val, vu);
64+
}
65+
});
66+
5167
useEffect(() => {
52-
if (!view.current && editor.current) {
68+
if (!view.current && editor.current && originalExtension && modifiedExtension) {
5369
view.current = new MergeView({
5470
a: {
5571
...original,
5672
extensions: [
5773
...(originalExtension?.extension || []),
5874
...getDefaultExtensions({ ...originalExtension?.option, theme }),
75+
originalUpdateListener,
5976
],
6077
},
6178
b: {
6279
...modified,
6380
extensions: [
6481
...(modifiedExtension?.extension || []),
6582
...getDefaultExtensions({ ...modifiedExtension?.option, theme }),
83+
modifiedUpdateListener,
6684
],
6785
},
6886
parent: editor.current,
6987
...opts,
7088
});
7189
}
72-
}, [view, editor]);
90+
}, [view, editor, originalExtension, modifiedExtension]);
7391

7492
useEffect(() => {
7593
if (original && original.doc && view.current) {

merge/src/Modified.tsx

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useEffect } from 'react';
22
import { getDefaultExtensions, DefaultExtensionsOptions } from '@uiw/react-codemirror';
33
import { EditorStateConfig, Extension } from '@codemirror/state';
4-
import { EditorView, ViewUpdate } from '@codemirror/view';
4+
import { ViewUpdate } from '@codemirror/view';
55
import { useStore } from './store';
66

77
export interface ModifiedProps extends Omit<DefaultExtensionsOptions, 'theme'>, Omit<EditorStateConfig, 'doc'> {
@@ -15,30 +15,20 @@ export const Modified = (props: ModifiedProps): JSX.Element | null => {
1515
const { extensions = [], value, selection, onChange, ...otherOption } = props;
1616
const { theme, dispatch } = useStore();
1717
const defaultExtensions = getDefaultExtensions({ ...otherOption, theme });
18-
const updateListener = EditorView.updateListener.of((vu: ViewUpdate) => {
19-
if (vu.docChanged && typeof onChange === 'function') {
20-
const doc = vu.state.doc;
21-
const val = doc.toString();
22-
onChange(val, vu);
23-
}
24-
});
25-
26-
useEffect(
27-
() =>
28-
dispatch!({
29-
modified: {
30-
doc: value,
31-
selection: selection,
32-
extensions: [updateListener, ...defaultExtensions, ...extensions],
33-
},
34-
modifiedExtension: {
35-
onChange,
36-
option: otherOption,
37-
extension: [updateListener, extensions],
38-
},
39-
}),
40-
[props],
41-
);
18+
useEffect(() => {
19+
dispatch!({
20+
modified: {
21+
doc: value,
22+
selection: selection,
23+
extensions: [...defaultExtensions, ...extensions],
24+
},
25+
modifiedExtension: {
26+
onChange,
27+
option: otherOption,
28+
extension: [extensions],
29+
},
30+
});
31+
}, [props]);
4232
return null;
4333
};
4434

merge/src/Original.tsx

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useEffect } from 'react';
22
import { getDefaultExtensions, DefaultExtensionsOptions } from '@uiw/react-codemirror';
33
import { EditorStateConfig, Extension } from '@codemirror/state';
4-
import { EditorView, ViewUpdate } from '@codemirror/view';
4+
import { ViewUpdate } from '@codemirror/view';
55
import { useStore } from './store';
66

77
export interface OriginalProps extends Omit<DefaultExtensionsOptions, 'theme'>, Omit<EditorStateConfig, 'doc'> {
@@ -15,26 +15,19 @@ export const Original = (props: OriginalProps): JSX.Element | null => {
1515
const { extensions = [], value, selection, onChange, ...otherOption } = props;
1616
const { theme, dispatch } = useStore();
1717
const defaultExtensions = getDefaultExtensions({ ...otherOption, theme });
18-
const updateListener = EditorView.updateListener.of((vu: ViewUpdate) => {
19-
if (vu.docChanged && typeof onChange === 'function') {
20-
const doc = vu.state.doc;
21-
const val = doc.toString();
22-
onChange(val, vu);
23-
}
24-
});
2518

2619
useEffect(
2720
() =>
2821
dispatch!({
2922
original: {
3023
doc: value,
3124
selection: selection,
32-
extensions: [updateListener, ...defaultExtensions, ...extensions],
25+
extensions: [...defaultExtensions, ...extensions],
3326
},
3427
originalExtension: {
3528
onChange,
3629
option: otherOption,
37-
extension: [extensions, updateListener],
30+
extension: [extensions],
3831
},
3932
}),
4033
[props],

www/src/pages/merge/examples/Example.md

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,24 @@ four
1313
five`;
1414

1515
export default function App() {
16-
const [value, setValue] = useState('');
17-
const [valueModified, setValueModified] = useState('');
16+
const [value, setValue] = useState(doc);
17+
const [valueModified, setValueModified] = useState(doc);
1818
return (
1919
<div>
20-
<CodeMirrorMerge>
20+
<CodeMirrorMerge destroyRerender={false}>
2121
<Original
22-
onChange={(value) => {
23-
setValue(value);
22+
onChange={(val) => {
23+
console.log('~~:1', val);
24+
setValue(val);
2425
}}
25-
value={doc}
26+
value={value}
2627
/>
2728
<Modified
28-
onChange={(value) => {
29-
setValueModified(value);
29+
onChange={(val) => {
30+
console.log('~~:2', val);
31+
setValueModified(val);
3032
}}
31-
value={doc.replace(/t/g, 'T') + 'Six'}
33+
value={valueModified}
3234
/>
3335
</CodeMirrorMerge>
3436
<div style={{ display: 'flex', marginTop: 10 }}>

0 commit comments

Comments
 (0)