Skip to content

Instantly share code, notes, and snippets.

@behnamazimi
Last active May 22, 2020 07:55
Show Gist options
  • Save behnamazimi/7fb972af69dd3198799ee2043e8f5995 to your computer and use it in GitHub Desktop.
Save behnamazimi/7fb972af69dd3198799ee2043e8f5995 to your computer and use it in GitHub Desktop.
React component for Jodit HTML editor, module lazy loading support.
/**
* React component for Jodit HTML editor
* + Jodit module lazy loading support.
* + Debounce for change event to improve performance
*/
import React, {useEffect, useRef, forwardRef, useLayoutEffect, useMemo} from 'react'
import * as PropTypes from 'prop-types'
import 'jodit/build/jodit.min.css'
let CHANGE_DEBOUNCE_FLAG;
const HTMLEditor = forwardRef(({defaultValue, onChange, onBlur, tabIndex, name}, ref) => {
const textArea = useRef(null);
// jodit module loader on component mount
const JoditLoader = useMemo(() => {
return new Promise(resolve => {
import('jodit').then(res => resolve(res.default))
})
}, [])
// set the value of forwarded ref
useLayoutEffect(() => {
if (ref) {
if (typeof ref === 'function') {
ref(textArea.current)
} else {
ref.current = textArea.current
}
}
}, [textArea]);
// create instance of jodit
useEffect(() => {
const element = textArea.current;
(async () => {
const Jodit = await JoditLoader;
const config = {
buttons: "bold,strikethrough,underline,italic,eraser,|,superscript,subscript,|,ul,ol,|,outdent,indent,|,font,fontsize,brush,paragraph,|,table,link,image,|,align,,undo,redo,|,dots,strikethrough,underline,,selectall,cut,copy,paste,symbol,print,fullsize",
toolbarAdaptive: false,
}
textArea.current = Jodit.make(element, config);
textArea.current.value = defaultValue;
textArea.current.events.on('blur', () => blurHandler(textArea.current.value));
textArea.current.events.on('change', () => changeHandler(textArea.current.value));
textArea.current.workplace.tabIndex = tabIndex || -1;
})();
return () => {
textArea.current.destruct();
textArea.current = element;
}
}, []);
useEffect(() => {
if (textArea && textArea.current) {
textArea.current.value = defaultValue
}
}, [textArea, defaultValue]);
function blurHandler(newContent) {
if (onBlur && typeof onBlur === "function") {
onBlur(newContent)
}
}
function changeHandler(newContent) {
if (CHANGE_DEBOUNCE_FLAG)
clearTimeout(CHANGE_DEBOUNCE_FLAG);
CHANGE_DEBOUNCE_FLAG = setTimeout(() => {
if (onChange && typeof onChange === "function") {
onChange(newContent)
}
}, 300)
}
return <textarea ref={textArea} name={name}/>
});
HTMLEditor.propTypes = {
defaultValue: PropTypes.string,
name: PropTypes.string,
tabIndex: PropTypes.number,
onChange: PropTypes.func,
onBlur: PropTypes.func
};
export default HTMLEditor
@ryanlrs
Copy link

ryanlrs commented May 22, 2020

Would you happened to have a Typescript version of this wrapper?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment