I just want a simple WYSIWYG editor with a minimal set of features.
I'd prefer not to use a third party reactjs integration project as it seems these projects are often not fully up to date and maintained.
Is there some instructions somewhere for a simple way to run Quill in ReactJS?
thanks
Hi @lunikernel,
I don't know of such guide. Have you seen zenoamaro/react-quill? Would that be helpful to check an approach to use Quill with React?
Cheers.
Just in case, you can create an instance of a Quill() in componentDidMount() and also immediately subscribe to its on('text-change') events. Filter out source==='api' and record 'user' changes to your DB periodically (I do each 250ms):
componentDidMount() {
this.editor = new Quill(this.editorRef.current, this.options);
this.editor.setText('');
this.editor.clipboard.dangerouslyPasteHTML(0, TextItem.getText(this.props));
this.editor.on('text-change', this.onChange);
}
componentDidUpdate(prevProps) {
if(TextItem.getText(prevProps) != TextItem.getText(this.props)){
this.editor.setText('');
this.editor.clipboard.dangerouslyPasteHTML(0, TextItem.getText(this.props));
}
}
onChange = (value, delta, source) => {
/* Sort out API updates to avoid loop component updates */
if(source === 'api'){
return;
}
this.html = this.editor.root.innerHTML;
if (this.onChangeTimeout) {
clearTimeout(this.onChangeTimeout);
this.onChangeTimeout = null;
}
this.onChangeTimeout = setTimeout(() => this.commitValue(), 250);
}
commitValue() {
clearTimeout(this.onChangeTimeout);
this.onChangeTimeout = null;
if (this.props.isEditable) {
this.props.textUpdateHandler(this.html);
}
}
render() {
const isReadOnly = !this.props.isEditable || (this.props.isEditable && !this.props.selected);
return (
<div className={bem.block()}>
<div className={bem.element('positioner', {
position: this.props.config.position,
})}
>
<div ref={this.editorRef}
className={bem.element('editor', {
readonly: isReadOnly,
})}
>
</div>
</div>
</div>
);
}
@ilya-spy do you happen to have a working example of the above code you could share?
@allenwipf I have a component that creates quill directly, and it's working good for me. Above mentioned zenoamaro/react-quill integration seems to have issue with re-creating a quill instance too often, affecting performance and sometimes toolbar disappears while you work with it.
import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import Quill from 'quill';
import { variableType } from 'enums/variablesTypes';
import { getBrowserStatus } from 'reducers/browser';
import { BROWSER_TEXT_READY } from 'actions/browser';
import 'quill/dist/quill.bubble.css';
import './TextItem.scss';
import { html } from 'components/HtmlComponent';
const bem = html.bem('TextItem');
const gridBem = html.bem('EditorGrid');
var Size = Quill.import('attributors/style/size');
Size.whitelist = [
'1em', '1.25em', '1.5em', '2em', '3em', '4em'
];
Quill.register(Size, true);
var FontAttributor = Quill.import('formats/font');
FontAttributor.whitelist = [
'open-sans', 'roboto', 'proza-libre'
];
Quill.register(FontAttributor, true);
Quill.debug(false);
@connect(
state => ({
textReady: getBrowserStatus(state).code === BROWSER_TEXT_READY,
})
)
export default class TextItem extends React.PureComponent {
static propTypes = {
isEditable: PropTypes.bool,
selected: PropTypes.bool,
config: PropTypes.object,
textUpdateHandler: PropTypes.func,
variables: PropTypes.arrayOf(variableType),
};
static defaultProps = {
variables: [],
};
static textItemProperties = [
'text',
'position'
];
static getText(props) {
return props.config.text
}
onChangeTimeout = null;
editorRef = React.createRef();
editor = null;
html = null;
userUpdate = false;
options = {
readOnly: !this.props.selected,
bounds: '.' + gridBem.block(),
theme: 'bubble',
modules: {
toolbar: [
[
{ 'header': '1'}, {'header': '2'}, { 'font': ['','open-sans', 'roboto', 'proza-libre'] },
{'size': ['1em', '1.25em', '1.5em', '2em', '3em', '4em']}
],
['bold', 'italic', 'underline'],
[{ 'color': [] }, { 'background': [] }],
[{ 'align': ['','center','right'] }],
[{ 'list': 'ordered'}, {'list': 'bullet'}],
]
},
formats:
['align', 'background', 'header', 'font', 'size', 'align', 'bold', 'italic', 'underline',
'strike', 'script', 'list', 'bullet', 'indent', 'link', 'color', 'clean'],
}
componentDidMount() {
this.editor = new Quill(this.editorRef.current, this.options);
this.editor.root.innerHTML = TextItem.getText(this.props);
this.editor.update();
this.editor.on('text-change', this.onChange);
}
componentDidUpdate() {
if( this.props.textReady ){
this.editor.root.innerHTML = TextItem.getText(this.props);
this.editor.update();
}
}
onChange = (value, delta, source) => {
/* source === api | user */
if(source === 'api'){
return;
}
this.html = this.editor.root.innerHTML;
if (this.onChangeTimeout) {
clearTimeout(this.onChangeTimeout);
this.onChangeTimeout = null;
}
this.onChangeTimeout = setTimeout(() => this.commitValue(), 300);
}
commitValue() {
clearTimeout(this.onChangeTimeout);
this.onChangeTimeout = null;
if (this.props.isEditable) {
this.userUpdate = true;
this.props.textUpdateHandler(this.html);
}
}
render() {
const isReadOnly = !this.props.isEditable || (this.props.isEditable && !this.props.selected);
return (
<div className={bem.block()}>
<div className={bem.element('positioner', {
position: this.props.config.position,
})}
>
<div ref={this.editorRef}
className={bem.element('editor', {
readonly: isReadOnly,
})}
>
</div>
</div>
</div>
);
}
}
Thank you ilya-spy but your code is a little hard to understand because it imports other custom made components. Do anyone has a code on github that use redux or not, at least react ?
Most helpful comment
@allenwipf I have a component that creates quill directly, and it's working good for me. Above mentioned zenoamaro/react-quill integration seems to have issue with re-creating a quill instance too often, affecting performance and sometimes toolbar disappears while you work with it.