in packages-rc/rc-codemirror/src/rc/codemirror/index.tsx [48:118]
function CodeMirror({
conf,
convertValueToDisplay,
convertValueFromDisplay,
linesMin = DEFAULT_LINE_MIN,
linesMax = DEFAULT_LINE_MAX,
value = '',
onChange,
...props
}: IPropsCodeMirror, ref: TCodeMirrorRef): JSX.Element {
const [stateEditorDom, setStateEditorDom] = useState<HTMLDivElement | null>(null);
const [stateEditor, setStateEditor] = useState<Editor | null>(null);
const [stateDisplayValue, setStateDisplayValue] = useState<string>(convertValue(value, convertValueToDisplay));
const prevValue = usePrevious(value);
const handleChange = useCallback((editor: Editor) => {
const newValue = editor.getValue();
setStateDisplayValue(newValue);
onChange?.(convertValue(newValue, convertValueFromDisplay));
}, [convertValueFromDisplay, onChange]);
useEffect(() => {
if (!stateEditorDom || stateEditor) {
return;
}
const editor: Editor = createEditor(stateEditorDom, stateDisplayValue, conf); // TODO 要不要更新 conf?
_forEach(conf?.on, (fn, k) => editor.on(k as keyof EditorEventMap, fn));
setStateEditor(editor);
}, [conf, stateEditorDom, stateEditor, stateDisplayValue, setStateEditor]);
// onChange 变化则更新之,需要解除旧有的
useEffect(() => {
if (!stateEditor) {
return;
}
stateEditor.on('change', handleChange);
return () => stateEditor.off('change', handleChange);
}, [handleChange, stateEditor]);
useEffect(() => {
if (!stateEditor) {
return;
}
const newDisplayValue = convertValue(value, convertValueToDisplay);
if (prevValue !== value && stateDisplayValue !== newDisplayValue) {
setStateDisplayValue(newDisplayValue);
stateEditor.setValue(newDisplayValue);
}
}, [prevValue, value, stateDisplayValue, convertValueToDisplay, stateEditor]);
useEffect(() => { // CodeMirror 未提供 destroy 方法,只需要解除实例的引用即可
return () => setStateEditor(null);
}, [setStateEditor]);
return <div ref={ref}>
<Wrapper ref={setStateEditorDom} {...{
...props,
linesMin,
linesMax
}} />
</div>;
}