¿Es componentDidMount()
una buena práctica usar como función asíncrona en React Native o debería evitarlo?
Necesito obtener información de AsyncStorage
cuándo se monta el componente, pero la única forma que sé de hacerlo es hacer que la componentDidMount()
función sea asíncrona.
async componentDidMount() {
let auth = await this.getAuth();
if (auth)
this.checkAuth(auth);
}
¿Hay algún problema con eso y hay otras soluciones para este problema?
reactjs
asynchronous
react-native
Mirakurun
fuente
fuente
Respuestas:
Comencemos señalando las diferencias y determinando cómo podría causar problemas.
Aquí está el código del
componentDidMount()
método de ciclo de vida asíncrono y "sincronizado" :Al mirar el código, puedo señalar las siguientes diferencias:
async
palabras clave: en mecanografiado, esto es simplemente un marcador de código. Hace 2 cosas:Promise<void>
lugar devoid
. Si especifica explícitamente que el tipo de devolución no es prometedor (por ejemplo, nulo), el mecanografiado le arrojará un error.await
palabras clave dentro del método.void
aPromise<void>
async someMethod(): Promise<void> { await componentDidMount(); }
Ahora puede usar la
await
palabra clave dentro del método y pausar temporalmente su ejecución. Me gusta esto:Ahora, ¿cómo podrían causar problemas?
async
palabra clave es absolutamente inofensiva.No puedo imaginar ninguna situación en la que necesite hacer una llamada al
componentDidMount()
método, por lo que el tipo de retorno tambiénPromise<void>
es inofensivo.Llamar a un método que tiene tipo de retorno de
Promise<void>
sinawait
palabra clave no hará ninguna diferencia de llamar a uno que tiene tipo de retorno devoid
.Dado que no hay métodos de ciclo de vida después de
componentDidMount()
retrasar su ejecución, parece bastante seguro. Pero hay una trampa.Digamos que lo anterior
this.setState({users, questions});
se ejecutará después de 10 segundos. En medio del tiempo de retraso, otro ...this.setState({users: newerUsers, questions: newerQuestions});
... se ejecutaron con éxito y el DOM se actualizó. El resultado fue visible para los usuarios. El reloj siguió marcando y transcurrieron 10 segundos. El retraso
this.setState(...)
se ejecutaría y el DOM se actualizaría nuevamente, esa vez con usuarios antiguos y preguntas antiguas. El resultado también sería visible para los usuarios.=> Es bastante seguro (no estoy seguro del 100%) para usar
async
con elcomponentDidMount()
método. Soy un gran admirador y hasta ahora no he encontrado ningún problema que me dé mucho dolor de cabeza.fuente
setState()
siempre posee un pequeño riesgo. Debemos proceder con cuidado.isFetching: true
dentro del estado de un componente. Solo he usado esto con redux, pero supongo que es completamente válido con la administración de estado de solo reacción. Aunque en realidad no resuelve el problema de que el mismo estado se actualice en otro lugar del código ...isFetching
solución de bandera es bastante común, especialmente cuando queremos reproducir algunas animaciones en el front-end mientras esperamos la respuesta del back-end (isFetching: true
).Actualización de abril de 2020: el problema parece haberse solucionado en la última Reacción 16.13.1, consulte este ejemplo de sandbox . Gracias a @abernier por señalar esto.
He investigado un poco y he encontrado una diferencia importante: React no procesa errores de los métodos asíncronos del ciclo de vida.
Entonces, si escribes algo como esto:
entonces su error será detectado por el límite de errores , y puede procesarlo y mostrar un mensaje elegante.
Si cambiamos el código así:
que es equivalente a esto:
entonces su error será tragado en silencio . La culpa es tuya, reacciona ...
Entonces, ¿cómo procesamos los errores que? La única forma parece ser una captura explícita como esta:
o así:
Si aún queremos que nuestro error alcance el límite de error, puedo pensar en el siguiente truco:
render
métodoEjemplo:
fuente
Tu código está bien y es muy legible para mí. Vea este artículo de Dale Jefferson donde muestra un
componentDidMount
ejemplo asíncrono y se ve muy bien también.Pero algunas personas dirían que una persona que lee el código puede suponer que React hace algo con la promesa devuelta.
Entonces, la interpretación de este código y si es una buena práctica o no es muy personal.
Si quieres otra solución, puedes usar promesas . Por ejemplo:
fuente
async
función en línea conawait
s dentro ...?(async () => { const data = await fetch('foo'); const result = await submitRequest({data}); console.log(result) })()
dóndefetch
ysubmitRequest
son funciones que devuelven promesas.Cuando usa
componentDidMount
sinasync
palabra clave, el documento dice esto:Si lo usa
async componentDidMount
, perderá esta capacidad: se producirá otro procesamiento DESPUÉS de que el navegador actualice la pantalla. Pero, si estás pensando en usar asíncrono, como buscar datos, no puedes evitar que el navegador actualice la pantalla dos veces. En otro mundo, no es posible PAUSAR componentDidMount antes de que el navegador actualice la pantallafuente
Actualizar:
(Mi versión: React 16, Webpack 4, Babel 7):
Al usar Babel 7 descubrirás:
Usando este patrón ...
te encontrarás con el siguiente error ...
Error de referencia no capturado: regeneratorRuntime no está definido
En este caso necesitará instalar babel-plugin-transform-runtime
https://babeljs.io/docs/en/babel-plugin-transform-runtime.html
Si por alguna razón no desea instalar el paquete anterior (babel-plugin-transform-runtime), entonces querrá apegarse al patrón Promise ...
fuente
Creo que está bien siempre y cuando sepas lo que estás haciendo. Pero puede ser confuso porque
async componentDidMount()
aún puede ejecutarse después de que secomponentWillUnmount
haya ejecutado y el componente se haya desmontado.También es posible que desee iniciar tareas sincrónicas y asincrónicas dentro
componentDidMount
. SicomponentDidMount
fuera asíncrono, tendría que poner todo el código síncrono antes del primeroawait
. Puede que no sea obvio para alguien que el código anterior al primero seawait
ejecuta sincrónicamente. En este caso, probablemente mantendríacomponentDidMount
sincronizado, pero lo llamaría a métodos de sincronización y asíncrono.Ya sea que elija
async componentDidMount()
los métodos decomponentDidMount()
llamada vs sincronizaciónasync
, debe asegurarse de limpiar los oyentes o los métodos asíncronos que aún pueden estar ejecutándose cuando el componente se desmonta.fuente
En realidad, la carga asíncrona en ComponentDidMount es un patrón de diseño recomendado a medida que React se aleja de los métodos de ciclo de vida heredados (componentWillMount, componentWillReceiveProps, componentWillUpdate) y pasa a Async Rendering.
Esta publicación de blog es muy útil para explicar por qué esto es seguro y para proporcionar ejemplos de carga asíncrona en ComponentDidMount:
https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html
fuente
Me gusta usar algo como esto
fuente