1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-09-01 19:22:35 +02: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? * Should component update?
* *
* @param {Object} props * @param {Object} props
* @return {Boolean} shouldUpdate * @return {Boolean}
*/ */
shouldComponentUpdate(props) { shouldComponentUpdate(props) {
// If any of the regular properties have changed, re-render.
if ( if (
props.index != this.props.index || props.index != this.props.index ||
props.marks != this.props.marks || props.marks != this.props.marks ||
@@ -87,10 +88,18 @@ class Leaf extends React.Component {
return true return true
} }
if (props.state.isBlurred) { // If the DOM text does not equal the `text` property, re-render, this can
return false // 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 { index, node, state } = props
const { start, end } = OffsetKey.findBounds(index, props.ranges) const { start, end } = OffsetKey.findBounds(index, props.ranges)
return state.selection.hasEdgeBetween(node, start, end) return state.selection.hasEdgeBetween(node, start, end)
@@ -187,10 +196,17 @@ class Leaf extends React.Component {
this.debug('updateSelection') this.debug('updateSelection')
} }
/**
* Render the leaf.
*
* @return {Element}
*/
render() { render() {
this.debug('render') this.debug('render')
const { node, index } = this.props const { props } = this
const { node, index } = props
const offsetKey = OffsetKey.stringify({ const offsetKey = OffsetKey.stringify({
key: node.key, key: node.key,
index index
@@ -203,18 +219,20 @@ class Leaf extends React.Component {
this.tmp.renders++ this.tmp.renders++
return ( return (
<span <span key={this.tmp.renders} data-offset-key={offsetKey}>
key={this.tmp.renders} {this.renderMarks(props)}
data-offset-key={offsetKey}
>
{this.renderMarks()}
</span> </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 // If the text is empty, we need to render a <br/> to get the block to have
// the proper height. // the proper height.
if (text == '') return <br /> if (text == '') return <br />
@@ -229,9 +247,16 @@ class Leaf extends React.Component {
return text return text
} }
renderMarks() { /**
const { marks, renderMark } = this.props * Render all of the leaf's mark components.
const text = this.renderText() *
* @param {Object} props
* @return {Element}
*/
renderMarks(props) {
const { marks, renderMark } = props
const text = this.renderText(props)
return marks.reduce((children, mark) => { return marks.reduce((children, mark) => {
const Component = renderMark(mark, marks) const Component = renderMark(mark, marks)