In my electron application, I have an xterm.js
terminal emulator, in one of my react tabs
. How do I preserve the state of this terminal so that when the use go out and back the text, cursor position etc still is there? the usual approach in react is just use state variables, set it in the parent component and pass it down to the child on renderer but since xterm.js isn't a react component itself, by now I have no idea how to do that.
currently I create the terminal like this:
import { useEffect, useRef, useState } from "react";
import { Terminal as TerminalType } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
//import { SearchAddon } from 'xterm-addon-search'
import 'xterm/css/xterm.css';
export const Terminal = () => {
const [terminal] = useState(new TerminalType({
cursorBlink: true,
cursorStyle: window.api.isWindows ? "bar" : "underline"
}));
useEffect(() => {
const fitAddon = new FitAddon();
terminal.loadAddon(fitAddon);
window.api.receive('terminal.incomingData', (data) => {
terminal.write(data);
});
terminal.open(document.getElementById('xterm-container') as HTMLElement);
terminal.onData((key) => {
window.api.send('terminal.keystroke', key);
});
fitAddon.fit();
// simulate enter press to show the initial prompt command
window.api.send('terminal.keystroke', '\r');
}, [terminal]);
return (
<div id="xterm-container"></div>
)
}
UPDATE 1:
Making the tab with forceRender={true}
does work:
<TabPanel key="3" forceRender={true}>
<Terminal />
</TabPanel>
But it keeps the rendering mounted all the time, not only when it's needed, i.e., the tab is actived. Better ways to solve this is welcome.
Also, I found an issue fitAddon.fit()
doesn't work when forceRender={true}
is set.