Hi. I’m trying to dynamically switch the theme with reconfigure(). I find that the view theme and the mode switch, but not the highlight theme, until I edit the text.
Here is an example. When rebuild is on, it creates a new CodeMirror view instance, and switching the theme switches the view theme and the highlight theme.
When rebuild is off, it tries to do a full reconfigure
. It switches the language and the view theme just fine, but the highlight theme doesn’t change until I edit the text.
Is there something I should do to get it to update the highlighting, or might this be a bug? I tried adding changes and that works, but only if I actually change the text. I looked for a way to refresh and redraw, and didn’t find any. That’s probably best, but without a manual redraw, automatic redraw will need to work, or I will just need to recreate the view (which I am doing for now).
The code is also here:
import React, { useState, useRef, useEffect } from "react";
import {
EditorView,
keymap,
} from '@codemirror/view'
import { EditorState } from '@codemirror/state'
import { history, historyKeymap } from '@codemirror/history'
import { indentOnInput, LanguageSupport } from '@codemirror/language'
import { defaultKeymap } from '@codemirror/commands'
import { javascriptLanguage } from '@codemirror/lang-javascript'
import { pythonLanguage } from '@codemirror/lang-python'
import { defaultHighlightStyle } from '@codemirror/highlight'
import {
oneDarkTheme,
oneDarkHighlightStyle
} from '@codemirror/theme-one-dark'
import pickBy from 'lodash/pickBy'
import "./style.css";
const languageExtensions = {
javascript: [new LanguageSupport(javascriptLanguage)],
python: [new LanguageSupport(pythonLanguage)],
}
const themeExtensions = {
light: [defaultHighlightStyle],
dark: [oneDarkTheme, oneDarkHighlightStyle]
}
const exampleCode = `// JavaScript line comment
# Python line comment
for (let i=1; i <= 100; i++) {
let s = '';
if (i % 3 == 0) s += 'Fizz';
if (i % 5 == 0) s += 'Buzz';
console.log(s.length ? s : i);
}
for i in range(50):
print(i)`;
export default function App() {
const [rebuild, setRebuild] = useState(true)
const [language, setLanguage] = useState('javascript');
const [theme, setTheme] = useState('light');
const container = useRef(null);
const editor = useRef(null);
useEffect(() => {
if (container.current) {
const extensions = [
history(),
indentOnInput(),
keymap.of([
...defaultKeymap,
...historyKeymap,
]),
...languageExtensions[language],
...themeExtensions[theme],
]
if (!editor.current) {
editor.current = new EditorView({
state: EditorState.create({
doc: exampleCode,
extensions,
}),
parent: container.current,
})
} else if (rebuild) {
const doc = editor.current.state.doc
editor.current.destroy()
editor.current = new EditorView({
state: EditorState.create({
doc: exampleCode,
extensions,
}),
parent: container.current,
})
} else {
editor.current.dispatch({
reconfigure: {
full: extensions,
}
})
}
}
}, [rebuild, language, theme, container, editor])
return (
<div>
<p className="buttons">
rebuild {rebuild ? 'on' : 'off'}{' '}
<button onClick={() => setRebuild(true)}>On</button>
<button onClick={() => setRebuild(false)}>Off</button>
</p>
<p className="buttons">
{language}{' '}
<button onClick={() => setLanguage('javascript')}>JavaScript</button>
<button onClick={() => setLanguage('python')}>Python</button>
</p>
<p className="buttons">
{theme}{' '}
<button onClick={() => setTheme('light')}>Light</button>
<button onClick={() => setTheme('dark')}>Dark</button>
</p>
<div className="code" ref={container}></div>
</div>
);
}
Thanks!