{"action":"created","issue":{"url":"https://api.github.com/repos/draft-js-plugins/draft-js-plugins/issues/1022","repository_url":"https://api.github.com/repos/draft-js-plugins/draft-js-plugins","labels_url":"https://api.github.com/repos/draft-js-plugins/draft-js-plugins/issues/1022/labels{/name}","comments_url":"https://api.github.com/repos/draft-js-plugins/draft-js-plugins/issues/1022/comments","events_url":"https://api.github.com/repos/draft-js-plugins/draft-js-plugins/issues/1022/events","html_url":"https://github.com/draft-js-plugins/draft-js-plugins/pull/1022","id":292034303,"number":1022,"title":"[mention-plugin] add 'ignoreEditorChange' flag to avoid incorrectly setting editor st…","user":{"login":"comatory","id":5990424,"avatar_url":"https://avatars0.githubusercontent.com/u/5990424?v=4","gravatar_id":"","url":"https://api.github.com/users/comatory","html_url":"https://github.com/comatory","followers_url":"https://api.github.com/users/comatory/followers","following_url":"https://api.github.com/users/comatory/following{/other_user}","gists_url":"https://api.github.com/users/comatory/gists{/gist_id}","starred_url":"https://api.github.com/users/comatory/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/comatory/subscriptions","organizations_url":"https://api.github.com/users/comatory/orgs","repos_url":"https://api.github.com/users/comatory/repos","events_url":"https://api.github.com/users/comatory/events{/privacy}","received_events_url":"https://api.github.com/users/comatory/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":{"login":"juliankrispel","id":1188186,"avatar_url":"https://avatars1.githubusercontent.com/u/1188186?v=4","gravatar_id":"","url":"https://api.github.com/users/juliankrispel","html_url":"https://github.com/juliankrispel","followers_url":"https://api.github.com/users/juliankrispel/followers","following_url":"https://api.github.com/users/juliankrispel/following{/other_user}","gists_url":"https://api.github.com/users/juliankrispel/gists{/gist_id}","starred_url":"https://api.github.com/users/juliankrispel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/juliankrispel/subscriptions","organizations_url":"https://api.github.com/users/juliankrispel/orgs","repos_url":"https://api.github.com/users/juliankrispel/repos","events_url":"https://api.github.com/users/juliankrispel/events{/privacy}","received_events_url":"https://api.github.com/users/juliankrispel/received_events","type":"User","site_admin":false},"assignees":[{"login":"juliankrispel","id":1188186,"avatar_url":"https://avatars1.githubusercontent.com/u/1188186?v=4","gravatar_id":"","url":"https://api.github.com/users/juliankrispel","html_url":"https://github.com/juliankrispel","followers_url":"https://api.github.com/users/juliankrispel/followers","following_url":"https://api.github.com/users/juliankrispel/following{/other_user}","gists_url":"https://api.github.com/users/juliankrispel/gists{/gist_id}","starred_url":"https://api.github.com/users/juliankrispel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/juliankrispel/subscriptions","organizations_url":"https://api.github.com/users/juliankrispel/orgs","repos_url":"https://api.github.com/users/juliankrispel/repos","events_url":"https://api.github.com/users/juliankrispel/events{/privacy}","received_events_url":"https://api.github.com/users/juliankrispel/received_events","type":"User","site_admin":false}],"milestone":null,"comments":4,"created_at":"2018-01-26T21:18:01Z","updated_at":"2018-04-11T08:12:56Z","closed_at":null,"author_association":"NONE","pull_request":{"url":"https://api.github.com/repos/draft-js-plugins/draft-js-plugins/pulls/1022","html_url":"https://github.com/draft-js-plugins/draft-js-plugins/pull/1022","diff_url":"https://github.com/draft-js-plugins/draft-js-plugins/pull/1022.diff","patch_url":"https://github.com/draft-js-plugins/draft-js-plugins/pull/1022.patch"},"body":"…ate when selecting mention\r\n\r\nPlease check out Contributing Guidelines. By following this template you help us to review your code.\r\nhttps://github.com/draft-js-plugins/draft-js-plugins/blob/master/CONTRIBUTING.md\r\n\r\n## Checklist\r\n\r\n- [x] Fix any eslint errors that occur\r\n- [ ] Update change-log for every plugin you touch\r\n- [ ] Add/Update tests if you add/change new functionality\r\n- [ ] Add/Update docs if you add/change functionality\r\n- [ ] Enable \"Allow edits from maintainers\" for this PR\r\n\r\n## Use-case/Problem\r\n\r\nI am quite unsure how to describe this problem because I noticed it in very specific scenarios and it took me some time to reliably reproduce it.\r\n\r\nI am trying to capture the current state of `MentionSuggestions` popover, to see whether it is currently opened or closed. For this, I'm using `onOpen` and `onClose` callbacks to set the state to my parent component. In my application code I use this state to control keyboard shortcuts.\r\n\r\nThis seems unreliable because for some reason there is a certain combination of mention text that calls callbacks `onClose` and then `onOpen` again and triggers `onSearchChange` callback unnecessarily. This in turn filters down suggestion, it's this part of code in `draft-js-mention-plugin/src/MentionSuggestions/index.js`: \r\n\r\n```\r\n    } else if (nextProps.suggestions.size > 0 && !nextProps.suggestions.equals(this.props.suggestions) && !this.state.isActive) {\r\n      this.openDropdown();\r\n    }\r\n```\r\n\r\nI think the best way to demonstrate is on this gif:\r\n\r\n![](https://dr5mo5s7lqrtc.cloudfront.net/items/1c2S2k1v2D0D0v2G1M3w/Screen%20Recording%202018-01-26%20at%2009.51%20odp..gif?X-CloudApp-Visitor-Id=2948220&v=d089541a)\r\n\r\nSteps to reproduce:\r\n\r\n1. Go to sandbox https://codesandbox.io/s/mj7xzp8p2j\r\n2. Trigger mention with \"@\"\r\n3. Select first suggestion \"Tester 1\"\r\n4. Move cursor before inserted mention, add space, move cursor back to beginning of editor\r\n5. Trigger mention and select suggestion \"User\"\r\n\r\n`Popover opened ?` is whether the popover is currently opened or not, you can see in the end that it is incorrect. The `No. of current suggestions` are the filtered suggestions passed down as props to `MentionSuggestions` component (this is incorrectly filtered down to 1). `Search value` is the value passed to `onSearchChange` callback. \r\n\r\nIn the end of the gif, you can see that for some reason the part of the text from _User_ suggestion is passed to it as _ser_. I am using keyboard to move between suggestion and confirming it by hitting ENTER.\r\n\r\nThis only happens with some of the suggestions. For example if the second mention that I'd insert was the one named \"Tester 2\", this would not happen.\r\n\r\n__After some further inspecting...__\r\n\r\nIt turns out this is caused by `Portal` component wrapping `MentionSuggestions`component. This \"portal\" component comes from `react-portal` library. I hear you, you can't be responsible for other people's code from other libraries. But I still find it quite interesting and since this plugin does not handle the suggestion pop up in containers with overflow (I use them in my application), I had to implement this somehow.\r\n\r\nSo... after removing the portal component, it's behaving a bit better:\r\n\r\n![](https://dr5mo5s7lqrtc.cloudfront.net/items/401w3l352p3R1Z1J1i09/Screen%20Recording%202018-01-26%20at%2010.08%20odp..gif?X-CloudApp-Visitor-Id=2948220&v=8f358553)\r\n\r\nYou can check it out here in this sandbox: https://codesandbox.io/s/lykwlzqz5z\r\n\r\nHowever this still does not play nice with my application code because as you can see the popover state is correctly assumed but `onSearchChange` callback is still called with the value that is part of the text in selected suggestion. And suggestions are still filtered to single item thanks to this even though I implemented `onAddMention` callback that resets the suggestions.\r\n\r\nSo after a lot of time (seriously around 1.5 day) I think I found the culprit. It's in `onMentionSelect` method where this is called:\r\n\r\n```\r\n    this.props.store.setEditorState(newEditorState);\r\n```\r\n\r\nThis kinda looks like it's async, so my reasoning is that the editor state is updated somewhere in between thus causing `onOpen` callback to be called.\r\n\r\n## Implementation\r\n\r\nI added simple flag `ignoreEditorChange` that is set to true before the state of the editor is updated via `this.props.store.setEditorState`. This in turn triggers `onEditorStateChange` method. If the flag is `true` then current editor state is return instead of continuing on and calling `onSearchChange` method.\r\n\r\n## Demo\r\n\r\nSee the GIFs above and codesandbox playgrounds. You can download the sandbox, it's packaged as app so you just `npm install` & `npm run`, it's probably easier to debug this way.\r\n\r\n## Note on versions\r\n\r\nI do realize I'm using older react and draft-js. I tried first matching the stuff from my application code, later I forked the codesandbox playground and updated all of the dependencies. It does not solve my problem."},"comment":{"url":"https://api.github.com/repos/draft-js-plugins/draft-js-plugins/issues/comments/380366838","html_url":"https://github.com/draft-js-plugins/draft-js-plugins/pull/1022#issuecomment-380366838","issue_url":"https://api.github.com/repos/draft-js-plugins/draft-js-plugins/issues/1022","id":380366838,"user":{"login":"comatory","id":5990424,"avatar_url":"https://avatars0.githubusercontent.com/u/5990424?v=4","gravatar_id":"","url":"https://api.github.com/users/comatory","html_url":"https://github.com/comatory","followers_url":"https://api.github.com/users/comatory/followers","following_url":"https://api.github.com/users/comatory/following{/other_user}","gists_url":"https://api.github.com/users/comatory/gists{/gist_id}","starred_url":"https://api.github.com/users/comatory/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/comatory/subscriptions","organizations_url":"https://api.github.com/users/comatory/orgs","repos_url":"https://api.github.com/users/comatory/repos","events_url":"https://api.github.com/users/comatory/events{/privacy}","received_events_url":"https://api.github.com/users/comatory/received_events","type":"User","site_admin":false},"created_at":"2018-04-11T08:12:56Z","updated_at":"2018-04-11T08:12:56Z","author_association":"NONE","body":"Hey @juliankrispel. Thanks for the reply, I'll dig in more. The reason why I laid it out here like this was to see if you'd get some _\"AHA\"_ moment if this issue was caused by something obvious to you. I see that this is not the case.\r\n\r\nI'll update the PR once I find the problem."}}
{"actor":{"display_login":"comatory"}}