mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-18 13:11:17 +02:00
fix change queueing in <Editor> (#1196)
This commit is contained in:
@@ -109,8 +109,8 @@ class Editor extends React.Component {
|
|||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.tmp = {}
|
|
||||||
this.state = {}
|
this.state = {}
|
||||||
|
this.tmp = {}
|
||||||
|
|
||||||
// Create a new `Stack`, omitting the `onChange` property since that has
|
// Create a new `Stack`, omitting the `onChange` property since that has
|
||||||
// special significance on the editor itself.
|
// special significance on the editor itself.
|
||||||
@@ -118,10 +118,12 @@ class Editor extends React.Component {
|
|||||||
const stack = Stack.create({ plugins })
|
const stack = Stack.create({ plugins })
|
||||||
this.state.stack = stack
|
this.state.stack = stack
|
||||||
|
|
||||||
// Resolve the state, running `onBeforeChange` first.
|
// Run `onBeforeChange` on the passed-in state because we need to ensure
|
||||||
|
// that it is normalized, and queue the resulting change.
|
||||||
const change = props.state.change()
|
const change = props.state.change()
|
||||||
stack.onBeforeChange(change, this)
|
stack.onBeforeChange(change, this)
|
||||||
const { state } = change
|
const { state } = change
|
||||||
|
this.queueChange(change)
|
||||||
this.cacheState(state)
|
this.cacheState(state)
|
||||||
this.state.state = state
|
this.state.state = state
|
||||||
|
|
||||||
@@ -164,17 +166,34 @@ class Editor extends React.Component {
|
|||||||
this.setState({ stack })
|
this.setState({ stack })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve the state, running the `onBeforeChange` handler of the stack.
|
// Run `onBeforeChange` on the passed-in state because we need to ensure
|
||||||
|
// that it is normalized, and queue the resulting change.
|
||||||
const change = props.state.change()
|
const change = props.state.change()
|
||||||
stack.onBeforeChange(change, this)
|
stack.onBeforeChange(change, this)
|
||||||
const { state } = change
|
const { state } = change
|
||||||
|
this.queueChange(change)
|
||||||
this.cacheState(state)
|
this.cacheState(state)
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache a `state` in memory to be able to compare against it later, for
|
* When the component first mounts, flush any temporary changes.
|
||||||
* things like `onDocumentChange`.
|
*/
|
||||||
|
|
||||||
|
componentDidMount = () => {
|
||||||
|
this.flushChange()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the component updates, flush any temporary change.
|
||||||
|
*/
|
||||||
|
|
||||||
|
componentDidUpdate = () => {
|
||||||
|
this.flushChange()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache a `state` object to be able to compare against it later.
|
||||||
*
|
*
|
||||||
* @param {State} state
|
* @param {State} state
|
||||||
*/
|
*/
|
||||||
@@ -184,6 +203,37 @@ class Editor extends React.Component {
|
|||||||
this.tmp.selection = state.selection
|
this.tmp.selection = state.selection
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queue a `change` object, to be able to flush it later. This is required for
|
||||||
|
* when a change needs to be applied to the state, but because of the React
|
||||||
|
* lifecycle we can't apply that change immediately. So we cache it here and
|
||||||
|
* later can call `this.flushChange()` to flush it.
|
||||||
|
*
|
||||||
|
* @param {Change} change
|
||||||
|
*/
|
||||||
|
|
||||||
|
queueChange = (change) => {
|
||||||
|
if (change.operations.length) {
|
||||||
|
debug('queueChange', { change })
|
||||||
|
this.tmp.change = change
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush a temporarily stored `change` object, for when a change needed to be
|
||||||
|
* made but couldn't because of React's lifecycle.
|
||||||
|
*/
|
||||||
|
|
||||||
|
flushChange = () => {
|
||||||
|
const { change } = this.tmp
|
||||||
|
|
||||||
|
if (change) {
|
||||||
|
debug('flushChange', { change })
|
||||||
|
this.props.onChange(change)
|
||||||
|
delete this.tmp.change
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Programmatically blur the editor.
|
* Programmatically blur the editor.
|
||||||
*/
|
*/
|
||||||
@@ -229,6 +279,7 @@ class Editor extends React.Component {
|
|||||||
change = (fn) => {
|
change = (fn) => {
|
||||||
const change = this.state.state.change()
|
const change = this.state.state.change()
|
||||||
fn(change)
|
fn(change)
|
||||||
|
debug('change', { change })
|
||||||
this.onChange(change)
|
this.onChange(change)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,15 +294,18 @@ class Editor extends React.Component {
|
|||||||
throw new Error('As of slate@0.22.0 the `editor.onChange` method must be passed a `Change` object not a `State` object.')
|
throw new Error('As of slate@0.22.0 the `editor.onChange` method must be passed a `Change` object not a `State` object.')
|
||||||
}
|
}
|
||||||
|
|
||||||
const { onChange, onDocumentChange, onSelectionChange } = this.props
|
|
||||||
const { stack } = this.state
|
const { stack } = this.state
|
||||||
const { document, selection } = this.tmp
|
|
||||||
const { state } = change
|
|
||||||
if (state == this.state.state) return
|
|
||||||
|
|
||||||
stack.onBeforeChange(change, this)
|
stack.onBeforeChange(change, this)
|
||||||
stack.onChange(change, this)
|
stack.onChange(change, this)
|
||||||
|
|
||||||
|
const { state } = change
|
||||||
|
const { document, selection } = this.tmp
|
||||||
|
const { onChange, onDocumentChange, onSelectionChange } = this.props
|
||||||
|
|
||||||
|
if (state == this.state.state) return
|
||||||
|
|
||||||
|
debug('onChange', { change })
|
||||||
onChange(change)
|
onChange(change)
|
||||||
if (onDocumentChange && state.document != document) onDocumentChange(state.document, change)
|
if (onDocumentChange && state.document != document) onDocumentChange(state.document, change)
|
||||||
if (onSelectionChange && state.selection != selection) onSelectionChange(state.selection, change)
|
if (onSelectionChange && state.selection != selection) onSelectionChange(state.selection, change)
|
||||||
|
Reference in New Issue
Block a user