redux - tics - las tic en la educacion pdf
Reactivo-reductor: ¿el renderizado siempre debe ocurrir en el mismo tic que despachar una acción? (4)
Actualización asincrónica sin perder la posición nunca fue compatible
La solución es rastrear la posición del cursor y usar una ref
dentro de componentDidUpdate()
para colocar el cursor correctamente.
Información adicional:
Cuando configura atributos en reaccionar, internamente sucede esto:
node.setAttribute(attributeName, '''' + value);
Cuando establece el value
esta manera, el comportamiento es inconsistente:
Usar setAttribute () para modificar ciertos atributos, el más notable es el valor en XUL, funciona de manera inconsistente, ya que el atributo especifica el valor predeterminado.
--- https://developer.mozilla.org/en/docs/Web/API/Element/setAttribute
En cuanto a su pregunta sobre si el procesamiento se produce de forma síncrona, setState()
reaccion es asíncrono y se usa internamente por react-redux:
No hay garantía de una operación sincrónica de las llamadas a setState y las llamadas se pueden agrupar para obtener mejoras en el rendimiento
--- https://facebook.github.io/react/docs/react-component.html#setstate
Hay una broma interna en el equipo que React debería haberse llamado "Horario" porque React no quiere ser completamente "reactivo".
--- https://facebook.github.io/react/contributing/design-principles.html#scheduling
En mi aplicación react-redux, tengo una entrada de texto controlada. Cada vez que el componente cambia de valor, distribuye una acción y, al final, el valor regresa a través del bucle redux y se representa.
En el ejemplo a continuación, esto funciona bien, pero en la práctica, me he encontrado con un problema donde la representación ocurre de forma asíncrona desde el despacho de acción y la entrada pierde la posición del cursor. Para demostrar el problema, agregué otra entrada con un retraso puesto explícitamente. Agregar un espacio en medio de una palabra hace que el cursor salte en la entrada asíncrona.
Tengo dos teorías sobre esto y me gustaría saber cuál es cierto:
- Esto debería funcionar, pero tengo un error en alguna parte de mi aplicación de producción que causa el retraso
- El hecho de que funcione en el ejemplo simple es solo suerte y react-redux no garantiza que el renderizado ocurra sincrónicamente
¿Cuál es la correcta?
Ejemplo de trabajo:
http://jsbin.com/doponibisi/edit?html,js,output
const INITIAL_STATE = {
value: ""
};
const reducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case ''SETVALUE'':
return Object.assign({}, state, { value: action.payload.value });
default:
return state;
}
};
const View = ({
value,
onValueChange
}) => (
<div>
Sync: <input value={value} onChange={(e) => onValueChange(e.target.value)} /><br/>
Async: <input value={value} onChange={(e) => { const v = e.target.value; setTimeout(() => onValueChange(v), 0)}} />
</div>
);
const mapStateToProps = (state) => {
return {
value: state.value
};
}
const mapDispatchToProps = (dispatch) => {
return {
onValueChange: (value) => {
dispatch({
type: ''SETVALUE'',
payload: {
value
}
})
}
};
};
const { connect } = ReactRedux;
const Component = connect(
mapStateToProps,
mapDispatchToProps
)(View);
const { createStore } = Redux;
const store = createStore(reducer);
ReactDOM.render(
<Component store={store} />,
document.getElementById(''root'')
);
EDITAR: pregunta aclaratoria
Marco y Nathan han señalado correctamente que este es un problema conocido en React que no se solucionará. Si hay un setTimeout
u otro retraso entre onChange
y el ajuste del valor, la posición del cursor se perderá.
Sin embargo, el hecho de que setState solo programe una actualización no es suficiente para provocar este error. En el número de Github que Marco vincula, hay un comentario:
En términos generales, setState no pospone el renderizado, está realizando actualizaciones por lotes y las ejecuta inmediatamente cuando el trabajo actual de React haya finalizado, no habrá ningún fotograma de renderizado intermedio. Entonces, en cierto sentido, la operación es sincrónica con respecto al marco de representación actual. setTimeout lo programa para otro marco de renderizado.
Esto se puede ver en el ejemplo de JsBin: la versión "sincronización" también usa setState, pero todo está funcionando.
La pregunta abierta sigue siendo: ¿hay algo dentro de Redux que cree un retraso que permita un marco de renderizado intermedio, o podría usarse Redux de una manera que evite esos retrasos?
Las soluciones para el problema en cuestión no son necesarias, encontré una que funciona en mi caso, pero estoy interesado en encontrar la respuesta a la pregunta más general.
EDITAR: problema resuelto
Estaba contento con la respuesta de Clarks e incluso otorgué la recompensa, pero resultó que estaba mal cuando realmente lo probé al eliminar todos los middlewares. También encontré el problema de Github relacionado con esto.
https://github.com/reactjs/react-redux/issues/525
La respuesta es:
- este es un problema en react-redux que se fijará con react-redux 5.1 y reaccionará v16
¿Qué middleware estás usando en tu aplicación Redux? Quizás uno de ellos está envolviendo una promesa en sus despachos de acción. Usar Redux sin middleware no muestra este comportamiento, por lo que creo que probablemente sea algo específico de tu configuración.
Creo que react-redux y redux son totalmente irrelevantes para su caso, esto es puro comportamiento React. React-redux eventualmente llama a setState en tu componente, no hay magia.
El problema de que async setState crea un marco de representación entre el renderizado de reacción y el evento nativo del navegador es porque el mecanismo de actualización por lotes solo se produce en el controlador de eventos sintéticos de React y en los métodos del ciclo de vida. Puede consultar esta publicación para más detalles.
El problema no está relacionado con Redux, sino con Reaccionar. Es un problema conocido y no se solucionará en el núcleo de React, ya que no se considera un error sino una "función no admitida".
Esta respuesta explica el escenario perfectamente.
Se han realizado algunos intentos para abordar este problema, pero como puede ver, todos incluyen un componente envoltorio alrededor de la entrada, por lo que es una solución muy desagradable si me preguntan.