简体   繁体   English

将React与不受控制的第三方组件一起使用

[英]Using React with uncontrolled third-party components

I'd like to create a UI similar to JSFiddle using React: 我想使用React创建一个类似于JSFiddle的UI:

  • A panel for HTML, CSS and JS HTML,CSS和JS面板
  • A preview panel 预览面板
  • A single "Run" button that updates the preview 单个“运行”按钮可更新预览

I'd like to use Microsoft's Monaco editor for the HTML, CSS and JS panels to get syntax highlight and autocomplete. 我想将Microsoft的Monaco编辑器用于HTML,CSS和JS面板,以突出显示语法并自动完成。

I've abstracted out a generic MonacoEditor component. 我已经提取了通用的MonacoEditor组件。 My component hierarchy looks something like this: 我的组件层次结构如下所示:

<Root>
  <div>HTML <MonacoEditor /></div>
  <div>CSS <MonacoEditor /></div>
  <div>JS <MonacoEditor /></div>
  <button onClick={this.run}>Run</button>
  <PreviewPanel />
</Root>

If I were implementing this UI in Vanilla JS, the run() method would call getValue() on each Monaco instance to extract the full text from each panel and generate the preview. 如果我在Vanilla JS中实现此UI,则run()方法将在每个Monaco实例上调用getValue()以从每个面板中提取全文并生成预览。

This becomes awkward with React, however, since the run() method can't call methods on instances of child components. 但是,由于React run()方法无法在子组件实例上调用方法,因此这对于React来说变得很尴尬。

One workaround would be for the MonacoEditor to have an onUpdate prop which gets fired on every keystroke. 一种解决方法是让MonacoEditor具有onUpdate道具,该道具会在每次击键时触发。 The Root component could store the provisional contents of each panel for when the "Run" button was clicked. Root组件可以存储单击“运行”按钮时每个面板的临时内容。 This is what I might do if each editor were a <textarea> . 如果每个编辑器都是<textarea> ,我可能会这样做。 But it's a non-starter with Monaco. 但这对摩纳哥来说并不是一个开始。 Serializing the text of the editor on every keystroke makes it unusably slow. 在每次击键时序列化编辑器的文本都会使其变得异常缓慢。

The only other approach I can think of is passing in a "getter setter" to the MonacoEditor component, eg: 我能想到的唯一其他方法是将“ getter setter”传递给MonacoEditor组件,例如:

class Root extends React.Component {
  render() {
    return (
      <div>
        <MonacoEditor setGetter={getter => this.getHTML=getter} />
        <MonacoEditor setGetter={getter => this.getCSS=getter} />
        <MonacoEditor setGetter={getter => this.getJS=getter} />
        <button onClick={() => this.run()}>Run</button>
        <PreviewPanel />
      </div>
    );
  }

  run() {
    const html = this.getHTML();
    const css = this.getCSS();
    const js = this.getJS();
    // ...
  }
}

But this feels extremely awkward and counter to the idea of one-way databinding. 但这感觉非常尴尬,与单向数据绑定的想法背道而驰。 Is there a better, more idiomatic approach? 有没有更好,更惯用的方法?

You can checkout react-monaco-editor . 您可以签出react-monaco-editor

This will satisfy all your requirements! 这将满足您的所有要求! Especially getting value from the editor instance . 特别是从编辑器实例中获取价值

If not this, declare a function inside the editor component and use ref to call that function from other components. 如果不是这样,请在编辑器组件内部声明一个函数,然后使用ref从其他组件调用该函数。

Hope it helps! 希望能帮助到你!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM