Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[draft-js-resizeable-plugin] not working when added to an existent project #2272

Closed
vcarrasc opened this issue Aug 24, 2021 · 7 comments · Fixed by #2313
Closed

[draft-js-resizeable-plugin] not working when added to an existent project #2272

vcarrasc opened this issue Aug 24, 2021 · 7 comments · Fixed by #2313
Labels

Comments

@vcarrasc
Copy link

vcarrasc commented Aug 24, 2021

Environment

Operating System version: macOS 11.5.1
Browser version: Version 92.0.4515.159 (Official Build) (x86_64)

  • @draft-js-plugins/editor version:
  • plugin name and version: "@draft-js-plugins/resizeable": "^5.0.2",

Description

It seems the library has issues when being added to an existing project. In a fully new one, everything works fine.

The project I'm working on currently uses. However, when upgrading to the current version resizable stops working.

"draft-js": "^0.11.5",
    "draft-js-drag-n-drop-plugin": "^2.0.4",
    "draft-js-focus-plugin": "^3.0.1",
    "draft-js-image-plugin": "^2.0.7",
    "draft-js-linkify-plugin": "^2.0.2",
    "draft-js-mention-plugin": "^3.1.5",
    "draft-js-plugins-editor": "^3.0.0",
    "draft-js-resizeable-plugin": "^2.0.9",
    "draft-js-video-plugin": "^2.0.2",

Screenshot 2021-08-24 at 10 57 16

index.esm.js:91 Uncaught TypeError: Cannot read property 'getBoundingClientRect' of undefined
    at index.esm.js:91
    at HTMLUnknownElement.callCallback (react-dom.development.js:188)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:237)
    at invokeGuardedCallback (react-dom.development.js:292)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:306)
    at executeDispatch (react-dom.development.js:389)
    at executeDispatchesInOrder (react-dom.development.js:414)
    at executeDispatchesAndRelease (react-dom.development.js:3278)
    at executeDispatchesAndReleaseTopLevel (react-dom.development.js:3287)
    at forEachAccumulated (react-dom.development.js:3259)
    at runEventsInBatch (react-dom.development.js:3304)
    at runExtractedPluginEventsInBatch (react-dom.development.js:3514)
    at handleTopLevel (react-dom.development.js:3558)
    at batchedEventUpdates$1 (react-dom.development.js:21871)
    at batchedEventUpdates (react-dom.development.js:795)
    at dispatchEventForLegacyPluginEventSystem (react-dom.development.js:3568)
    at attemptToDispatchEvent (react-dom.development.js:4267)
    at dispatchEvent (react-dom.development.js:4189)
    at unstable_runWithPriority (scheduler.development.js:653)
    at dispatchUserBlockingUpdate (react-dom.development.js:4172)
(anonymous) @ index.esm.js:91
callCallback @ react-dom.development.js:188
invokeGuardedCallbackDev @ react-dom.development.js:237
invokeGuardedCallback @ react-dom.development.js:292
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:306
executeDispatch @ react-dom.development.js:389
executeDispatchesInOrder @ react-dom.development.js:414
executeDispatchesAndRelease @ react-dom.development.js:3278
executeDispatchesAndReleaseTopLevel @ react-dom.development.js:3287
forEachAccumulated @ react-dom.development.js:3259
runEventsInBatch @ react-dom.development.js:3304
runExtractedPluginEventsInBatch @ react-dom.development.js:3514
handleTopLevel @ react-dom.development.js:3558
batchedEventUpdates$1 @ react-dom.development.js:21871
batchedEventUpdates @ react-dom.development.js:795
dispatchEventForLegacyPluginEventSystem @ react-dom.development.js:3568
attemptToDispatchEvent @ react-dom.development.js:4267
dispatchEvent @ react-dom.development.js:4189
unstable_runWithPriority @ scheduler.development.js:653
dispatchUserBlockingUpdate @ react-dom.development.js:4172
@vcarrasc vcarrasc added the bug label Aug 24, 2021
@fxOne
Copy link
Collaborator

fxOne commented Aug 25, 2021

What kind of element are you trying to resize? It looks like it doesn't set the ref which it should. The source can be found here:

const b = wrapper.current!.getBoundingClientRect();

@nperichSYKES
Copy link

nperichSYKES commented Aug 26, 2021

I just noticed this error as well (Cannot read property 'getBoundingClientRect' of undefined), though haven't yet figured out exactly what's going on. I get the error when hovering over or clicking on an image.

I've had draft plugins in my project for a long time without an issue. I did update draft-js-plugin dependencies recently, and confirmed that the older build with the older draft-js-plugins works fine (I don't believe I changed other code here). I'll post more as I learn more.

As far as I can tell, my error appears to be in the Alignment plugin. For example, the error sends me here:

var createDecorator = (function (_ref) {
  var store = _ref.store;
  return function (WrappedComponent) {
    var BlockAlignmentDecorator = /*#__PURE__*/React.forwardRef(function (_ref2, _ref3) {
      var blockProps = _ref2.blockProps,
          block = _ref2.block,
          style = _ref2.style,
          elementProps = _objectWithoutPropertiesLoose(_ref2, _excluded);

      var wrapper = useRef();
      useEffect(function () {
        if (blockProps.isFocused && blockProps.isCollapsedSelection) {
          var boundingRect = wrapper.current.getBoundingClientRect();
          store.updateItem('setAlignment', blockProps.setAlignment);
          store.updateItem('alignment', blockProps.alignment);
          store.updateItem('boundingRect', boundingRect);
          store.updateItem('visibleBlock', block.getKey()); // Only set visibleBlock to null in case it's the current one. This is important
          // in case the focus directly switches from one block to the other. Then the
          // Alignment tool should not be hidden, but just moved.
        } else if (store.getItem('visibleBlock') === block.getKey()) {
          store.updateItem('visibleBlock', null);
        }
      }, [blockProps.isFocused, blockProps.isCollapsedSelection, store]);
      var alignment = blockProps.alignment;
      var newStyle = style;

      if (alignment === 'left') {
        newStyle = _extends({}, style, {
          "float": 'left'
        });
      } else if (alignment === 'right') {
        newStyle = _extends({}, style, {

@fxOne
Copy link
Collaborator

fxOne commented Aug 27, 2021

@nperichSYKES can you create a codesandbox eample?

@nperichSYKES
Copy link

I'll focus on this Monday and see if I can figure anything out.

@nperichSYKES
Copy link

nperichSYKES commented Aug 30, 2021

Ok, here you go. This is the image example in the docs with an imageComponent option added. (EDIT: I updated it to a working version)
https://codesandbox.io/s/brave-glade-h90ct?file=/src/App.js

  • Since the last release of my app still works, I downgraded draft-js-plugins to those releases, then upgraded one by one systematically.
  • The issue only shows up when moving from either Alignment 4.1.0 or Resizable 4.1.0 to the 5.x.x release. Everything else upgrades fine. (For the plugins I use at least)
  • It seems the problem (for me) might be related to using a custom imageComponent.

@fxOne
Copy link
Collaborator

fxOne commented Aug 31, 2021

You should be able to fix the issue by adding a forwardRef for your image:

const imagePlugin = createImagePlugin({
  decorator,
  imageComponent: React.forwardRef(({
    block,
    className,
    theme = {},
    blockProps,
    customStyleMap,
    customStyleFn,
    decorator,
    forceSelection,
    offsetKey,
    selection,
    tree,
    contentState,
    ...elementProps
  },ref) => {
    const { src } = contentState.getEntity(block.getEntityAt(0)).getData();
    console.log("src is accurate: ", src);

    return <img src={src} {...elementProps} ref={ref} />;
  })
});

Maybe we should notice it in the docs.

@nperichSYKES
Copy link

Thanks, yeah that makes sense as a first step. If ref behavior was changed internally, it's definitely worth updating the docs and attaching a Breaking Change warning to the changelog with 5.x with a hint about wrapping imageComponent with forwardRef.

However, though just adding forwardRef did fix the minimal example I posted, it didn't fix my actual code. And I assume that most people who bother to use imageComponent would also still run into a further issue.

For whoever comes here later (and for when you update the docs!), it seems the problem with upgrading to 5.x when using the imageComponent setting is that you no longer have access to the element. So, to take a simple example just to illustrate, if you want to display the height of the image after it loads, ref.current on the <img ref={ref} /> will be undefined because of forwardRef. So you can't go ref.current.height to read it.

As far as I can tell, the best solution is to use an obscure React utility called useImperativeHandle.
https://reactjs.org/docs/hooks-reference.html#useimperativehandle

At least to me, it wasn't entirely clear exactly how you use this...and if you just follow the React doc examples to just add the "handles" you need, it won't really work. Since, I think (?), it won't actually carry over everything draft-js-plugins needs. But I figured out that you can just return the entire current state of the forwarded ref:

const innerRef = useRef();
useImperativeHandle(ref, () => innerRef.current);

I updated my Code Sandbox with an example of how this could work:
https://codesandbox.io/s/brave-glade-h90ct?file=/src/App.js:1496-1577

I'm not sure this is the best way to do it, or there isn't a gotcha. It seems pretty ugly. But it seems to work for now...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants