jpuri / react-draft-wysiwyg

A Wysiwyg editor build on top of ReactJS and DraftJS. https://jpuri.github.io/react-draft-wysiwyg
MIT License
6.38k stars 1.16k forks source link

Editor re-renders every time I write inside and it is causing blinking effect. #1406

Closed jacoblsdev closed 8 months ago

jacoblsdev commented 8 months ago

Code which is causing re-renders

  // ** useEffects
  useEffect(() => {
    if (!editorState) {
      return
    }

    let html = convertToHTML(editorState.getCurrentContent())
    setExtractedData(html) // -- This Line
  }, [editorState, setExtractedData])

Code in parent Component. // ** useEffects
useEffect(() => { setValue('add_info', extractedData) }, [extractedData, setValue])

I already tried everything. useMemo, callbacks, moved editor to parent.

My full Editor code.

const TextEditor = ({ setExtractedData, stored }) => {
  // ** dynamic imports **
  const Editor = dynamic(() => import('react-draft-wysiwyg').then(mod => mod.Editor), { ssr: false })

  // ** states
  const [editorState, setEditorState] = useState(EditorState.createEmpty())

  // ** theme
  const theme = useTheme()

  // ** useEffects
  useEffect(() => {
    if (!editorState) {
      return
    }

    let html = convertToHTML(editorState.getCurrentContent())
    setExtractedData(html)
  }, [editorState, setExtractedData])

  // ! editor not working
  useEffect(() => {
    if (!stored) {
      return
    }

    setEditorState(EditorState.createWithContent(convertFromHTML(stored)))
  }, [stored])

  // ** handle functions
  const handleEditorChange = state => {
    setEditorState(state)
  }

  // ** custom toolbar option
  const toolbarOptions = {
    options: ['inline', 'blockType', 'list', 'textAlign', 'link', 'image', 'history'],
    blockType: {
      inDropdown: true,
      options: ['Normal', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'Blockquote']
    }
  }

  return (
    <Box
      sx={{
        '.editor-wrapper': {},
        '.editor-class': {
          minHeight: '30vh',
          maxHeight: '30vh',
          border: `2px solid ${theme.palette.divider}`,
          padding: '10px',
          lineHeight: '100%',
          borderRadius: '20px',
          cursor: 'text',
          overflow: 'scroll'
        },
        '.editor-toolbar': {
          bgcolor: theme.palette.divider,
          padding: '10px',
          outline: `3px solid ${theme.palette.divider}`,
          marginBottom: '10px',
          borderRadius: '15px',
          outlineOffset: '2px',
          border: 'none',
          width: 'auto',
          '*': {
            color: 'black'
          }
        },
        '.rdw-dropdown-carettoopen': {
          display: 'none'
        },
        '.rdw-dropdown-carettoclose': {
          display: 'none'
        },
        '.rdw-suggestion-popup': {
          color: 'red'
        }
      }}
    >
      <Editor
        editorState={editorState}
        onEditorStateChange={handleEditorChange}
        wrapperClassName='editor-wrapper'
        editorClassName='editor-class'
        toolbarClassName='editor-toolbar'
        placeholder='Add Event Information Here'
        toolbar={toolbarOptions}
      />
      {/* <div dangerouslySetInnerHTML={createMarkup(extractedData)}></div>  */}
    </Box>
  )
}

Parent code where i am calling This editor custom component.

const AdditionalInfoEditor = ({ setValue, stored, getValues }) => {
  // ** states
  const [extractedData, setExtractedData] = useState()

  // ** useEffects
  useEffect(() => {
    setValue('add_info', extractedData)
  }, [extractedData, setValue])

  return <TextEditor setExtractedData={setExtractedData} getValues={getValues} stored={stored} />
}
jacoblsdev commented 8 months ago

I resolved issue by importing memorized editor in next js.

  const MyEditor = useMemo(
    () => dynamic(() => import('react-draft-wysiwyg').then(mod => mod.Editor), { ssr: false }),
    []
  )