使用react-monaco-editor正确地消除对onChange的调用进行更新

问题描述 投票:0回答:4

编辑:

这个问题很好地总结了我的问题:摩纳哥编辑器从状态中获取当前值,而反跳则阻止状态触发。如何允许用户不间断地继续输入而不进行不必要的调用来更新代码。

-----编辑结束-----

好吧,我有一个使用react-monaco-editor作为代码编辑器面板的react应用程序(没有CRA)。当用户键入时,会触发 onChange 事件,我想调用去抖动更新操作,但这现在不起作用。

设置并不完全简单,但我有一个父组件 CodeEditorPanel,它有一个子组件 monacoEditor。我已经删除了尽可能多与问题不直接相关的代码,但如果需要,可以添加更多详细信息。

在自动模式(UPDATE_METHODS.AUTOMATIC.value)中使用updateCode效果很好,但计算成本很高,但是当我使用去抖模式(UPDATE_METHODS.DEBOUNCE.value)时,更改会变得混乱,看起来像是在使用旧值(听起来就像如果我没有使用 useRef 但我使用了会发生什么。)。无论如何,有些事情(不是那么)显然不对,我将不胜感激任何帮助来发现我的(希望是小)错误。

// CodeEditorPanel.js
import React, { useRef } from 'react';

const CodeEditorPanel = ({
  updateMethod, // editor setting, user can choose: automatic, manual, throttled, debounced
  updateCode, // the update action I want to debounce
}) => {

  const debouncedUpdate = useRef(debounce(updateCode, debounceInterval)).current;

  const getUpdateMethod = () => {
    switch (updateMethod) {
      case UPDATE_METHODS.DEBOUNCE.value:
        return debouncedUpdate;
      case UPDATE_METHODS.THROTTLE.value:
        return throttledUpdate;
      case UPDATE_METHODS.MANUAL.value:
        return ({ code, selectedFile }) => updateCode({ code, selectedFile, buffer: true });
      case UPDATE_METHODS.AUTOMATIC.value:
      default:
        return updateCode;
    }
  };

  // in reality there is a function call before update getUpdateMethod but I'm trying to simplify
  return <MonacoEditor updateCode={getUpdateMethod()} />;

};

// 
class monacoEditor extends Component {

  onChange(newValue, e) {
    const { selectedFile, updateCode } = this.props;

    // want to debounce this bad boy right here
    updateCode({ code: newValue, selectedFile });
  }

  render() {
    <MonacoEditor
      ref="monaco"
      language={language}
      theme="vs-dark"
      defaultValue=""
      value={selectedFile.content}
      options={MONACO_DEFAULT_OPTIONS}
      onChange={this.onChange}
      editorWillMount={this.editorWillMount}
      editorDidMount={this.editorDidMount}
    />
  }

}
javascript reactjs monaco-editor
4个回答
1
投票

我提出了一种适合我的解决方案,但如果其他人有想法,我仍然感兴趣。

所以我所做的是:

  1. 在我的组件中创建一个本地状态变量并初始化为代码属性。
  2. 在 onChange 方法中,我没有调用操作创建者,而是更新本地状态。
  3. 我向组件添加了一个空闲计时器,设置为一秒。因此,如果用户停止输入一秒钟,它将调用操作创建者来更新 redux。

0
投票

我的方法有两个:

  1. 如果需要立即采取行动(例如代码完成),那么我会在每次更改时执行任务。

  2. 如果某个操作可以延迟(例如错误检查),那么实际的更改并不重要。在这种情况下,我启动一个计时器(每次更改时都会重置)并在触发后运行所需的操作。在这种情况下不需要保持状态,因为没有必要。

当然,如果实际的更改仍然很重要(例如,将操作限制在自上次运行以来修改的某个范围内),那么您当然需要存储它(或派生值,例如范围)。


0
投票

反应摩纳哥编辑器

我还有一个想法,可以在不调用 onChange 事件的情况下获取 React monacoeditor 值。 创建 MonacoEditor 的引用。

this.editorRef = React.createRef();

之后添加对 MonacoEditor 标签的引用。

<MonacoEditor
   ref={this.editorRef}
   height="500px"
   language="json"
   // editorDidMount={this.editorDidMount.bind(this)}
   // onChange={this.onChange.bind(this)}
   value={this.state.code}
   options={options}
 />

然后添加按钮并为 onClick 事件创建函数,如下代码

 async saveData(){
    const currentCode = this.editorRef.current.editor.getModel().getValue();
    this.setState({code:currentCode});
    this.editorRef.current.editor?.focus();

  }

您将通过单击“保存”按钮获得编辑器的更新值。


0
投票

我也有同样的问题,我想在编辑器的 onChange 中执行一个函数,它将值写入 url,但它与 onChange 状态发生冲突,并使光标突然移动到编辑器的末尾。

这是我解决问题的方法:

正如@cbutler提到的,首先在我的组件中创建一个本地状态变量并初始化为代码属性。

const [currentConfig, setCurrentConfig] = useState<string>(config);

然后在 onChange 方法中,不调用操作创建者,而是更新本地状态。

 const handleEditorChange: OnChange = (value) => {
    setCurrentConfig(value || "");
};

<Editor
 defaultValue={config}
 value={config}
 onMount={editorDidMount}
 height="100%"
 width={"100%"}
 defaultLanguage="yaml"
 theme="vs-dark"
 options={{
 quickSuggestions: { other: true, strings: true },
 automaticLayout: true,
 minimap: { enabled: false },
 scrollbar: { verticalScrollbarSize: 5 },
 padding: { top: 10 },
 }}
 onChange={handleEditorChange}
/>

最后添加了这段useEffect代码:

useEffect(() => {
    onChangeConfig(currentConfig);
}, [currentConfig]);
© www.soinside.com 2019 - 2024. All rights reserved.