From 519e2d4f03d4f2b44e29d8b616359c5defd30b4f Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 3 Aug 2021 19:55:20 +0800 Subject: [PATCH 1/2] fix: the problem 're-render all content when japanese \/ chinese input' --- src/component/base/DraftEditor.react.js | 33 +++++++++++++++++-- .../DraftEditorContents-core.react.js | 12 +++++++ .../DraftEditorCompositionHandler.js | 9 ++++- .../DraftEditorCompostionHandler-test.js | 1 + src/model/immutable/BlockKeyMap.js | 14 ++++++++ 5 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 src/model/immutable/BlockKeyMap.js diff --git a/src/component/base/DraftEditor.react.js b/src/component/base/DraftEditor.react.js index 92d7c7b379..e721035dd7 100644 --- a/src/component/base/DraftEditor.react.js +++ b/src/component/base/DraftEditor.react.js @@ -16,6 +16,7 @@ import type {BlockMap} from 'BlockMap'; import type {DraftEditorModes} from 'DraftEditorModes'; import type {DraftEditorDefaultProps, DraftEditorProps} from 'DraftEditorProps'; import type {DraftScrollPosition} from 'DraftScrollPosition'; +import type {BlockKeyMap} from 'BlockKeyMap'; const DefaultDraftBlockRenderMap = require('DefaultDraftBlockRenderMap'); const DefaultDraftInlineStyle = require('DefaultDraftInlineStyle'); @@ -40,6 +41,7 @@ const invariant = require('invariant'); const isHTMLElement = require('isHTMLElement'); const nullthrows = require('nullthrows'); const React = require('react'); +const {Map} = require('immutable'); const isIE = UserAgent.isBrowser('IE'); @@ -57,7 +59,7 @@ const handlerMap = { render: null, }; -type State = {contentsKey: number}; +type State = {contentsKey: number, blockKeyMap: BlockKeyMap}; let didInitODS = false; @@ -191,6 +193,7 @@ class DraftEditor extends React.Component { setMode: (mode: DraftEditorModes) => void; exitCurrentMode: () => void; restoreEditorDOM: (scrollPosition?: DraftScrollPosition) => void; + restoreBlockDOM: (key: string, scrollPosition?: DraftScrollPosition) => void; setClipboard: (clipboard: ?BlockMap) => void; getClipboard: () => ?BlockMap; getEditorKey: () => string; @@ -199,7 +202,7 @@ class DraftEditor extends React.Component { onDragLeave: () => void; // See `restoreEditorDOM()`. - state: State = {contentsKey: 0}; + state: State = {contentsKey: 0, blockKeyMap: new Map({})}; constructor(props: DraftEditorProps) { super(props); @@ -349,7 +352,7 @@ class DraftEditor extends React.Component { textAlignment, textDirectionality, } = this.props; - + const {contentsKey, blockKeyMap} = this.state; const rootClass = cx({ 'DraftEditor/root': true, 'DraftEditor/alignLeft': textAlignment === 'left', @@ -388,6 +391,7 @@ class DraftEditor extends React.Component { editorState, preventScroll, textDirectionality, + blockKeyMap, }; const contentClassName = @@ -598,6 +602,29 @@ class DraftEditor extends React.Component { this._handler = handler[mode]; }; + /** + * Used via `this.restoreBlockDOM()`. + * Force a complete re-render of the DraftEditorBlock in DraftEditorContents + * Search for a block with the specified block key and re-render it. + */ + restoreBlockDOM: ( + key: string, + scrollPosition?: DraftScrollPosition, + ) => void = (key: string, scrollPosition?: DraftScrollPosition): void => { + const {blockKeyMap} = this.state; + this.setState( + { + blockKeyMap: blockKeyMap.set( + key, + blockKeyMap.has(key) ? blockKeyMap.get(key) + 1 : 1, + ), + }, + () => { + this.focus(scrollPosition); + }, + ); + }; + // eslint-disable-next-line fb-www/extra-arrow-initializer exitCurrentMode: () => void = (): void => { this.setMode('edit'); diff --git a/src/component/contents/DraftEditorContents-core.react.js b/src/component/contents/DraftEditorContents-core.react.js index bc5eb9682d..f54cdb18fd 100644 --- a/src/component/contents/DraftEditorContents-core.react.js +++ b/src/component/contents/DraftEditorContents-core.react.js @@ -16,6 +16,7 @@ import type {DraftBlockRenderMap} from 'DraftBlockRenderMap'; import type {DraftInlineStyle} from 'DraftInlineStyle'; import type EditorState from 'EditorState'; import type {BidiDirection} from 'UnicodeBidiDirection'; +import type {BlockKeyMap} from 'BlockKeyMap'; const DraftEditorBlock = require('DraftEditorBlock.react'); const DraftOffsetKey = require('DraftOffsetKey'); @@ -38,6 +39,7 @@ type Props = { editorState: EditorState, preventScroll?: boolean, textDirectionality?: BidiDirection, + blockKeyMap: BlockKeyMap, ... }; @@ -85,11 +87,19 @@ class DraftEditorContents extends React.Component { const prevDirectionMap = prevEditorState.getDirectionMap(); const nextDirectionMap = nextEditorState.getDirectionMap(); + const prevBlockKeyMap = this.props.blockKeyMap; + const nextBlockKeyMap = nextProps.blockKeyMap; + // Text direction has changed for one or more blocks. We must re-render. if (prevDirectionMap !== nextDirectionMap) { return true; } + // blockKeyMap has chaged. We must re-render on block level. + if (prevBlockKeyMap !== nextBlockKeyMap) { + return true; + } + const didHaveFocus = prevEditorState.getSelection().getHasFocus(); const nowHasFocus = nextEditorState.getSelection().getHasFocus(); @@ -136,6 +146,7 @@ class DraftEditorContents extends React.Component { editorKey, preventScroll, textDirectionality, + blockKeyMap, } = this.props; const content = editorState.getCurrentContent(); @@ -181,6 +192,7 @@ class DraftEditorContents extends React.Component { preventScroll, selection, tree: editorState.getBlockTree(key), + key: `${key}-${blockKeyMap.get(key) || '0'}`, }; const configForType = diff --git a/src/component/handlers/composition/DraftEditorCompositionHandler.js b/src/component/handlers/composition/DraftEditorCompositionHandler.js index 07a0c2929b..977a9b6778 100644 --- a/src/component/handlers/composition/DraftEditorCompositionHandler.js +++ b/src/component/handlers/composition/DraftEditorCompositionHandler.js @@ -239,7 +239,7 @@ const DraftEditorCompositionHandler = { ); const compositionEndSelectionState = documentSelection.selectionState; - editor.restoreEditorDOM(); + // editor.restoreEditorDOM(); // See: // - https://github.com/facebook/draft-js/issues/2093 @@ -250,6 +250,13 @@ const DraftEditorCompositionHandler = { ? EditorState.forceSelection(editorState, compositionEndSelectionState) : EditorState.acceptSelection(editorState, compositionEndSelectionState); + const anchorKey = compositionEndSelectionState.getAnchorKey(); + const focusKey = compositionEndSelectionState.getFocusKey(); + + anchorKey === focusKey + ? editor.restoreBlockDOM(anchorKey) + : editor.restoreEditorDOM(); + editor.update( EditorState.push( editorStateWithUpdatedSelection, diff --git a/src/component/handlers/composition/__tests__/DraftEditorCompostionHandler-test.js b/src/component/handlers/composition/__tests__/DraftEditorCompostionHandler-test.js index 31750f20b6..d3bc91ca12 100644 --- a/src/component/handlers/composition/__tests__/DraftEditorCompostionHandler-test.js +++ b/src/component/handlers/composition/__tests__/DraftEditorCompostionHandler-test.js @@ -96,6 +96,7 @@ beforeEach(() => { setMode: jest.fn(), restoreEditorDOM: jest.fn(), exitCurrentMode: jest.fn(), + restoreBlockDOM: jest.fn(), update: jest.fn(state => (editor._latestEditorState = state)), }; }); diff --git a/src/model/immutable/BlockKeyMap.js b/src/model/immutable/BlockKeyMap.js new file mode 100644 index 0000000000..a420223d6a --- /dev/null +++ b/src/model/immutable/BlockKeyMap.js @@ -0,0 +1,14 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow strict-local + * @emails oncall+draft_js + */ + + 'use strict'; + + export type BlockKeyMap = Map; \ No newline at end of file From 3db9c588a31ddc4c581443b355c533112e22fae8 Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 11 Aug 2021 19:56:20 +0800 Subject: [PATCH 2/2] fix: new line IME error --- scripts/module-map.js | 4 ++-- src/component/contents/DraftEditorContents-core.react.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/module-map.js b/scripts/module-map.js index 6896a2f3ac..de34302c6f 100644 --- a/scripts/module-map.js +++ b/scripts/module-map.js @@ -8,7 +8,7 @@ module.exports = Object.assign( { immutable: 'immutable', - React: 'react', + react: 'react', ReactDOM: 'react-dom', ReactDOMComet: 'react-dom', 'object-assign': 'object-assign', @@ -17,5 +17,5 @@ module.exports = Object.assign( reactComponentExpect: 'react-dom/lib/reactComponentExpect', }, require('fbjs/module-map'), - require('fbjs-scripts/third-party-module-map') + require('fbjs-scripts/third-party-module-map'), ); diff --git a/src/component/contents/DraftEditorContents-core.react.js b/src/component/contents/DraftEditorContents-core.react.js index f54cdb18fd..6cc30f3439 100644 --- a/src/component/contents/DraftEditorContents-core.react.js +++ b/src/component/contents/DraftEditorContents-core.react.js @@ -243,7 +243,7 @@ class DraftEditorContents extends React.Component { const child = React.createElement( Element, childProps, - , + , ); processedBlocks.push({