1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-02-24 17:23:07 +01:00

fix leaf to re-render when DOM is mismatched

This commit is contained in:
Ian Storm Taylor 2016-08-02 10:31:25 -07:00
parent 7128085e9e
commit 197515e096

View File

@ -74,10 +74,11 @@ class Leaf extends React.Component {
* Should component update?
*
* @param {Object} props
* @return {Boolean} shouldUpdate
* @return {Boolean}
*/
shouldComponentUpdate(props) {
// If any of the regular properties have changed, re-render.
if (
props.index != this.props.index ||
props.marks != this.props.marks ||
@ -87,10 +88,18 @@ class Leaf extends React.Component {
return true
}
if (props.state.isBlurred) {
return false
}
// If the DOM text does not equal the `text` property, re-render, this can
// happen because React gets out of sync when previously natively rendered.
const el = findDeepestNode(ReactDOM.findDOMNode(this))
const text = this.renderText(props)
if (el.textContent != text) return true
// Otherwise, there aren't any content changes in this leaf, so if the
// selection is blurred we don't need to render to update it.
if (props.state.isBlurred) return false
// Otherwise, if it's focused, only re-render if this leaf contains one or
// both of the selection's edges.
const { index, node, state } = props
const { start, end } = OffsetKey.findBounds(index, props.ranges)
return state.selection.hasEdgeBetween(node, start, end)
@ -187,10 +196,17 @@ class Leaf extends React.Component {
this.debug('updateSelection')
}
/**
* Render the leaf.
*
* @return {Element}
*/
render() {
this.debug('render')
const { node, index } = this.props
const { props } = this
const { node, index } = props
const offsetKey = OffsetKey.stringify({
key: node.key,
index
@ -203,18 +219,20 @@ class Leaf extends React.Component {
this.tmp.renders++
return (
<span
key={this.tmp.renders}
data-offset-key={offsetKey}
>
{this.renderMarks()}
<span key={this.tmp.renders} data-offset-key={offsetKey}>
{this.renderMarks(props)}
</span>
)
}
renderText() {
const { text, index, ranges } = this.props
/**
* Render the text content of the leaf, accounting for browsers.
*
* @param {Object} props
* @return {Element}
*/
renderText({ text, index, ranges }) {
// If the text is empty, we need to render a <br/> to get the block to have
// the proper height.
if (text == '') return <br />
@ -229,9 +247,16 @@ class Leaf extends React.Component {
return text
}
renderMarks() {
const { marks, renderMark } = this.props
const text = this.renderText()
/**
* Render all of the leaf's mark components.
*
* @param {Object} props
* @return {Element}
*/
renderMarks(props) {
const { marks, renderMark } = props
const text = this.renderText(props)
return marks.reduce((children, mark) => {
const Component = renderMark(mark, marks)