rob-race / react-trix

React wrapper around Trix editor from Basecamp + some lightweight features
ISC License
213 stars 42 forks source link

It's not easy to initial value from API #35

Closed anhtran closed 4 years ago

anhtran commented 4 years ago

Normal way is not working. The editor is only show the start value is 000.

class MyTrixEditor extends Component {
  state = { content: '000' }

  componentDidMount () {
    loadFromAPI().then(r => { this.setState({ content: r.data }) })
  }

render () {
    return (
      <Editor
        mergeTags={null}
        value={this.state.content}
        onChange={this.handleChange}
        onEditorReady={this.handleEditorReady}
      />
    )
  }
}

I have to do something like this:

class MyTrixEditor extends Component {
  editor = null
  handleEditorReady = editor => {
    this.editor = editor
  }

  componentDidUpdate (prevProps, prevState, snapshot) {
    const { content } = this.state
    if (content && content !== prevState.content && this.editor) {
      this.editor.loadHTML('') // do this to avoid weird position of cursor
      this.editor.insertHTML(content)
      this.editor = null    // must add this to avoid repeat insert new value
    }
  }
}
dstpierre commented 4 years ago

@anhtran one option might be to load the editor once you're data is loaded pseudo code:

componentDidMount() {
  loadFromAPI().then(r => { this.setState({loaded: true, content: r.data }); });
}

render() {
  if (this.state.loaded) {
    return <Editor ... value={this.state.content} />
  } else {
    return <p>loading your data...</p>
  }
}

I've tried playing with fact that the internal editor could react to changing the value props after its loaded. It would be difficult to keep the onChange and keep updating on new props, causing a loop.

Depending on feedback, react-trix could offer two ways of handling this. But maybe the workaround above is acceptable for you.

Thanks for the feedback

lardissone commented 4 years ago

@dstpierre Is value property the correct way to load the HTML that comes from the API? Using insertString it renders the HTML as a string without formatting.

dstpierre commented 4 years ago

@lardissone the value property should load your HTML, it you need to re-load HTML once the editor is loaded you may use insertHTML :+1:

// Insert a bold “Hello” at the beginning of the document
editor.setSelectedRange([0, 0])
editor.insertHTML("<strong>Hello</strong>")