kenn
kenn

Reputation: 1494

Ace Editor updating react state

In my react app I have a component with two nodes, the first one is the ace editor component the second is an h1 HTML node. I also established a WebSocket connection to wss://echo.websocket.org which should return what I just sent.

What I wanted to achieve is in the ace editor on change the text input is sent to the server then the response from the server is rendered in the h1 node.

Currently, the character input into the ace editor is being sent and received from the server and rendered to the h1 node however only one character is being sent and received ie you cannot type more than two characters in the ace editor.

Having tried to debug, I found that when the set state in componentDidMount that should update the h1 is removed the ace editor you can type more than one character, however, I need to render the response from the server in the h1 tag.

Here is the code:


import React, { Component } from "react";
import AceEditor from "react-ace";
import "ace-builds/src-noconflict/mode-csharp";

class MirrorText extends Component {
  constructor(props) {
    super(props);
    this.state = {
      ws: '',
      dataFromServer: "", 
      };
  }



  onChange = (newValue) => {
    var obj = { action: "plan", payload: newValue };
    // Converting JS object to JSON string.
    var json = JSON.stringify(obj);
    try {

      this.state.ws.send(json) //send data to the server
    } catch (error) {
      console.log("error"+error) // catch error
    }

  }
  componentDidMount() {


    this.state.ws = new WebSocket("wss://echo.websocket.org")
    this.state.ws.onopen = () => {
      // on connecting, do nothing but log it to the console
      console.log('connected')
    }

    this.state.ws.onmessage = evt => {
      // listen to data sent from the websocket server
      // const message = JSON.parse(evt.data)

      this.setState({ dataFromServer: evt.data })
      console.log("message" + evt.data)
    }

    this.state.ws.onclose = () => {
      console.log('disconnected')

    }
  }



  render() {
    return (
      <div className="row" style={{ height: `99%`, width: `100%`, marginLeft: `5px`, marginRight: `2px` }}>
        <div
          className="col-xl-6 col-lg-6 col-sm-6"
          style={{ margin: 0, padding: 0 }}
        >
          <AceEditor
            mode="csharp"
            theme="twilight"
            style={{
              width: `100%`,
              height: `100%`,
              padding: `0`,
              margin: `0`
            }}
            onChange={this.onChange}
            setOptions={{
              showGutter: true,
              enableBasicAutocompletion: true,
              enableSnippets: true,
              enableLiveAutocompletion: true,
              value: this.state.rawModel
            }}
            name="1"
            editorProps={{
              $blockScrolling: true
            }}
          />
        </div>

        <div
          className="col-xl-6 col-lg-6 col-sm-6"
          style={{
            marginLeft: `0`,
          }}
        >
          <h1>{this.state.dataFromServer}</h1>

        </div>
      </div>
    );
  }
}



export default MirrorText;

How could I change the code to be able to type more than one character while keeping the functionality intact?

Thanks.

Upvotes: 0

Views: 1702

Answers (1)

a user
a user

Reputation: 24104

The issue happens because every time component updates it creates a new instance of ace. One workaround is to change the code initializing ace editor to

{this.editor || (this.editor = <AceEditor 
...
 />)}

https://codesandbox.io/s/beautiful-cray-2eipo

Upvotes: 1

Related Questions