Editar 2015
Alguien ha hecho un proyecto en NPM con mi solución: https://github.com/lovasoa/react-contenteditable
Edición 06/2016: Acabo de encontrar un nuevo problema que ocurre cuando el navegador intenta "reformatear" el html que le acaba de dar, lo que lleva a que el componente siempre vuelva a renderizarse. Ver
Edición 07/2016: aquí está mi contenido de producción Implementación editable. Tiene algunas opciones adicionales sobre las react-contenteditable
que quizás desee, que incluyen:
- cierre
- API imperativa que permite incrustar fragmentos html
- capacidad para reformatear el contenido
Resumen:
La solución de FakeRainBrigand me ha funcionado bastante bien durante algún tiempo hasta que tuve nuevos problemas. ContentEditables son una molestia, y no son realmente fáciles de manejar con React ...
Este JSFiddle demuestra el problema.
Como puede ver, cuando escribe algunos caracteres y hace clic en Clear
, el contenido no se borra. Esto se debe a que intentamos restablecer el contenteditable al último valor de dom virtual conocido.
Entonces parece que:
- Debes
shouldComponentUpdate
evitar los saltos de posición del cursor
- No puede confiar en el algoritmo de diferenciación VDOM de React si lo usa de
shouldComponentUpdate
esta manera.
Por lo tanto, necesita una línea adicional para que, siempre que shouldComponentUpdate
devuelva sí, esté seguro de que el contenido DOM está realmente actualizado.
Entonces, la versión aquí agrega ay se componentDidUpdate
convierte en:
var ContentEditable = React.createClass({
render: function(){
return <div id="contenteditable"
onInput={this.emitChange}
onBlur={this.emitChange}
contentEditable
dangerouslySetInnerHTML={{__html: this.props.html}}></div>;
},
shouldComponentUpdate: function(nextProps){
return nextProps.html !== this.getDOMNode().innerHTML;
},
componentDidUpdate: function() {
if ( this.props.html !== this.getDOMNode().innerHTML ) {
this.getDOMNode().innerHTML = this.props.html;
}
},
emitChange: function(){
var html = this.getDOMNode().innerHTML;
if (this.props.onChange && html !== this.lastHtml) {
this.props.onChange({
target: {
value: html
}
});
}
this.lastHtml = html;
}
});
El dom virtual permanece desactualizado y puede que no sea el código más eficiente, pero al menos funciona :) Mi error está resuelto
Detalles:
1) Si pones shouldComponentUpdate para evitar saltos de intercalación, entonces el contenteditable nunca se vuelve a reproducir (al menos en las pulsaciones de teclas)
2) Si el componente nunca se vuelve a reproducir con la pulsación de una tecla, React mantiene un dom virtual obsoleto para este contenteditable.
3) Si React mantiene una versión desactualizada de contenteditable en su árbol de dom virtual, entonces si intenta restablecer el contenteditable al valor desactualizado en el dom virtual, entonces durante la diferencia de dom virtual, React calculará que no hay cambios en aplicar al DOM!
Esto sucede principalmente cuando:
- tiene un contenteditable vacío inicialmente (shouldComponentUpdate = true, prop = "", vdom anterior = N / A),
- el usuario escribe algo de texto y evita las representaciones (shouldComponentUpdate = false, prop = text, previous vdom = "")
- después de que el usuario hace clic en un botón de validación, desea vaciar ese campo (shouldComponentUpdate = false, prop = "", vdom anterior = "")
- como tanto el vdom recién producido como el antiguo son "", React no toca el dom.
initialValue
enstate
y lo uso enrender
, pero no dejo Reaccionar actualización aún más.