logo

midudev


Transcribed podcasts: 167
Time transcribed: 5d 15h 37m 28s

This graph shows how many times the word ______ has been mentioned throughout the history of the program.

En la clase anterior has visto qué son y para qué sirven los React Custom Hooks
y en esta clase vas a ver diferentes casos de uso para refactorizar componentes de React
como podemos simplificarlos utilizando justamente estos Custom Hooks.
Vamos a verlo.
Aquí tendríamos uno bastante normal, el de, por ejemplo, ver si el usuario está logueado desde el principio.
Este user, set user, no sé qué.
Podríamos crear, vamos a crearlo por ahora aquí, use user.
Una vez que ves un useEffect, y esto es algo que te recomiendo un montón,
los useEffect, mucha gente se queja de que son complicados y tal.
Los useEffect habría que intentar utilizarlo lo mínimo posible, en el sentido de utilizarlo dentro de los componentes.
Y siempre que puedas, cuando tú veas un useEffect, preguntarte a ti mismo si no debería ser un Custom Hook.
Al final, un Custom Hook puede tener useStates, useEffects, puede tener y puedes utilizar cualquier tipo de Hook a su vez.
Al final, lo que son los Custom Hooks son Hooks que están compuestos de otros Hooks.
¿Ves? Aquí tendríamos el user.
Pues los traemos también y lo ponemos aquí.
¿Y ahora qué es lo que queremos devolver?
Pues vamos a querer devolver user y ya está.
A lo mejor lo único que queremos que devuelva el useUser a lo mejor es el user.
A lo mejor no queremos exponer cómo se actualiza el usuario.
¿Vale? Queremos que siempre lo haga de alguna forma, lo haga esto.
O a lo mejor queremos exponer un método para recuperar el usuario o para ver si puedes hacer login o lo que sea.
Pero a lo mejor no queremos que puedas hacer un setUser fuera de este Hook, que sea más de forma interna que este estado del usuario cambie.
De esta forma ahora, en lugar de hacer esto, ya podríamos hacer user, hacemos el useUser y todo esto ya nos lo podríamos petar.
Ahora si vamos otra vez a nuestra aplicación que tenemos por aquí, tenemos el user, login y ya lo tendríamos funcionando.
¿Qué más? ¿Qué más tendríamos aquí con el tema del useUser?
A ver, useUser...
Este useUser, obviamente, una cosa que es importante es que lo tengas en su propia carpeta, ¿vale?
Podríamos poner aquí el useUser.js.
Y este useUser, pues nada, los traemos en su propio fichero.
Hacemos un import aquí del useState y del useEffect.
Fíjate que además no necesitan importar React porque los hooks no deberían renderizar absolutamente...
Bueno, no deberían, ¿no? Que no pueden renderizar absolutamente nada y quedan pues mucho mejor, ¿no?
Al final lo que haces es una forma de poder reutilizar la lógica del hook.
Y con esto ya tendríamos el useUser, por ejemplo.
Ya lo podríamos importar, useUser from hooks, useUser.
UseUser y ya tendríamos aquí el usuario y poder utilizarlo sin problema.
Esto lo podríamos llevar también, pues por ejemplo, a la hora de recuperar las notas, ¿no?
Esto lo habíamos hecho aquí, pues useNotes.
Te doy una recomendación bastante importante con el tema de los custom hooks y los hooks en general, ¿vale?
¿Qué pasa? Nunca hagas custom hooks que te indiquen la implementación del hook.
¿Qué quiere decir esto?
Que, por ejemplo, hagamos useFetchNotes o useAPIFetchNotes.
Esto no está bien, ¿vale?
¿Por qué? Porque lo que estás haciendo ahí es que el nombre de tu custom hook sea la implementación.
Eso no está bien porque la implementación puede cambiar.
Lo mejor es que hagas useNotes o useFetchNotes.
Puede tener sentido porque fetch al final es un verbo que no tiene por qué significar que haces un fetch.
Al final lo podrías estar recuperando del local storage.
Lo interesante de los custom hooks es que son cajas negras que tú no sabes desde fuera cómo funcionan.
Así que intenta que sean nombres que no te digan exactamente lo que hacen.
Porque si no, ¿cuál es el sentido que tiene?
Pues tendríamos este useFetch, pues nada, lo mismo.
ExportDefault, Function, UseNotes.
Nada, sacaríamos de aquí el useState y este useFetch también.
La verdad es que mucha gente dice que cada vez que ves un useFetch deberías preguntarte si no debería ser un custom hook.
Y yo la verdad es que estoy bastante de acuerdo.
Porque los useFetch son bastante complicados a veces de que convivan en los componentes.
Ya veis que cuando tenéis aquí un useFetch se veía bastante tocho.
Entonces lo mejor normalmente es hacer un custom hook y poder reutilizarlo.
Y aunque no lo vayas a reutilizar, muchas veces te ayuda justamente a entender mejor qué es lo que se supone que está haciendo este custom hook.
O que sea que eso, una caja negra.
Es que al final es que es lo mejor que puede ser.
Que sean cajas negras en las que no te tengas que preocupar por tanto realmente lo que hace.
¿Ok?
Vale, pues aquí tendríamos el useNodes, el nodeService.
Esto solo lo recuperaríamos al llegar.
Pues ya tendríamos aquí, en lugar de tener todo el tema este de el useEffect dentro de la app.
Pues ya tendríamos aquí nodeService, useEffect, bla, bla, bla.
Nodes, useNodes.
Vale, ahora ya no tenemos por qué tener aquí los efectos.
Fíjate cómo ha quedado la app, mucho más sencilla, ¿no?
UseNodes, lo vamos a exportar de los hooks.
UseNodes.
¿Vale?
Y ahora pues ya quedaría así.
Esto además, este mismo...
Uy, es notExported.
Vale, perdón.
Que he hecho un exportDefault.
Fuera esto.
Y aquí que he hecho .services, esto es .services.
Y este, t, t, t, notes, useUser, esto también es de services.
Vale.
Y funciona correctamente.
Fíjate que todo esto de useNodes, que parecía una tontería, ¿no?
Pero ahora que lo teníamos en apps, que lo estamos extrayendo también, pues este mismo hook en la página de notas, que también necesita esto.
Pues mira, fíjate que aquí tenemos el user, aquí tenemos el tema de las notas, pues todo esto lo podríamos también refactorizar, ¿vale?
Así que ahí podríamos tener otra forma de hacerlo.
Por ejemplo, aquí tenemos SetNotes.
Aquí hay un tema importante, ¿vale?
Aunque tú veas aquí que tiene un estado, tú cada vez que utilices este custom hook, lo que está creando es un estado aparte, ¿vale?
Si tú utilizas este custom hook 80 veces, ten en cuenta que se están creando 80 estados.
Y el estado nos está compartiendo de forma automática.
Para hacer eso, que lo veremos más adelante, se tiene que utilizar el contexto de React, ¿vale?
Pero bueno, por ahora no lo vamos a saber.
A ver, aquí por ejemplo teníamos los...
Esto es la app, ¿vale?
Ah, bueno, esto no es la app.
Esto es que le dejamos el nombre de app a la página de notes, ¿vale?
Le vamos a poner el nombre correcto.
Y aquí igual, ¿no?
Teníamos UseNotes, Use...
No, Notes.
Aquí sí que voy a exponer el de SetNotes, pero teníamos UseNotes.
A ver, que se me importe automáticamente.
Y ya me podría quitar pues todo esto.
SetNotes, esto fuera también.
Mira, fíjate, ves que aquí, mira, este es interesante.
Voy a quitar este de SetNotes de aquí.
No, este de aquí no.
Esto lo voy a dejar aquí, SetNotes, y voy a quitar este de aquí.
Fíjate aquí, cualquier cosa.
Aquí en este Notes, este es UseNotes, no tengo el SetNotes, ¿no?
Solo tengo Notes.
Pero fíjate que aquí justamente tenemos una forma en la que se añade la nota.
O sea, aquí tengo un AddNote.
Este AddNote podría ser una forma justamente de ponerlo aquí en el UseNotes.
En lugar de tener este método aquí en el componente de notas, cuando al final esto podría estar en más de un sitio, ¿no?
El poder añadir una nota lo puedes hacer desde más de un sitio, no desde este componente y ya está.
Pues esto podrías moverlo aquí al UseNotes y este AddNote, pues lo podríamos poner aquí, básicamente.
Lo mismo, lo mismo podría ser con el ToggleImportanceOf, porque al final el cambiar la importancia de una nota puede ser que la hagamos en más de un sitio.
O sea, que este ToggleImportanceOf lo voy a mover también, ¿vale?
Y lo podríamos poner aquí.
¿Qué pasa con este ToggleImportanceOf?
Que este ToggleImportanceOf, fíjate que el catch estaba haciendo setErrorMessage y tal.
Puede tener sentido que haga un catch, pero no aquí.
A lo mejor tiene sentido que lo haga en el componente.
Pues lo que vamos a hacer es que lo que sí que tiene sentido, que se quede aquí, lo vamos a dejar aquí.
Vamos a devolver esta promesa que teníamos por aquí y este catch se lo vamos a dejar donde estaba, ¿vale? Así.
Así que ahora cuando hagamos este ToggleImportanceOf, vamos a importar de aquí el AddNote y el ToggleImportanceOf.
Pero este ToggleImportanceOf lo que va a hacer en realidad sería esto de aquí.
Sería llamar al ToggleImportanceOf de arriba, lo que pasa es que a este le vamos a llamar ToggleImportanceOfNode, por ejemplo.
¿Por qué? Porque este al final es el que está utilizando.
Lo vamos a quitar.
Este es el que estamos utilizando en el componente.
Pues vamos a buscarlo en el componente, ToggleImportanceOf, aquí, OfNode, tal.
Y este error message y todo esto lo vamos a hacer solo cuando el ToggleImportanceOf, que este es el que viene, el que viene del custom hook,
cuando peta, porque al final lo que hace es devolver una promesa, importante que tenemos que llamarlo,
ToggleImportanceOfID, que será este, le pasamos la ID, hace lo que tenga que hacer, devuelve la promesa,
si la promesa peta, podemos hacer un catch.
También podríamos hacer un .den, que nos puede ayudar justamente a cambiar el estado del loading.
Si estamos mostrando ahí que está haciendo un loading o lo que sea, ¿vale?
Ok.
Muy bien.
Perfecto.
Pues ahora lo que nos queda es probar si este pedazo de refactor con custom hook que hemos hecho funciona.
Venga, vamos a ver.
Notes, pues esto parece que aquí funciona bien.
Y entrando, pues perfectamente.
De esta forma, en el UseNotes, ahora lo estamos haciendo, utilizando en dos sitios, este custom hook.
Lo estamos utilizando en la app para recuperar las notas, porque en el detalle justamente necesitamos las notas y todo esto.
Lo que es muy interesante de esto, además en este custom hook, es que podríamos hacer algún tipo de caché de esto,
para evitar que cada vez que se llame, pues se utilice y tal.
Podríamos hacer que tenga un estado global, utilizando ya sea Redux o ya sea el Context API.
Al final aquí podríamos utilizar Redux con el UseSelector y recuperar esto del estado global.
Pero es totalmente agnóstico ahora para el componente.
Fíjate que el componente ahora ha quedado bastante más fácil de leerse, ¿no?
De hecho, mira, nos ha quedado este Token Importance Off, pero nos ha quedado el tema del Login y tal.
Pero el tema del Login, este HandleLogin y este HandleLogout, lo que hace aquí dentro realmente podría estar en el UseUser.
Exactamente lo mismo, porque este SetUser, SetUser, todo esto, mira, este UseEffect en realidad es que lo tenemos en el UseUser.
Esto ya no lo necesitaríamos porque está en el UseUser.
El HandleLogout al final lo que hace justamente es algo que debería estar en el UseUser.
O sea, que lo podríamos poner aquí y en lugar de HandleLogout le damos Logout directamente.
Pero es eso, fíjate que es un Custom Hook que ya tiene los métodos que puedes hacer con ese estado, ¿vale?
Lo digo, ¿por qué? Porque hay gente que los Custom Hooks lo que hace es meter un estado y te devuelve el SetUser y luego hace virguerías con el SetUser.
Y eso no te lo recomiendo, ¿vale?
Siempre que puedas, lo que tienes que hacer el Custom Hook es limitar las cosas que puedes hacer con ese estado, que esté controlado de alguna forma, ¿vale?
Así que esto lo podríamos quitar y esto aquí, a ver, SetToken, NodeService, esto más o menos se podría volver a hacer lo mismo.
Solo que cambia aquí el Set, esto podría devolver, el Login podría devolver esto.
Vale, estoy mirando a ver cómo lo podemos arreglar esto en un momento.
SetUsername, esto se le pasaría.
Vale, o sea, podríamos tener un Login, vamos a intentarlo.
Y esto sería Login.
Y vamos a extraer de aquí el PreventDefault, esto no tiene, o sea, esto sí que está bien que se quede en el componente.
Esto de User, pasándole Username y Password, esto se lo pasaremos como parámetros.
Pero todo esto, yo creo que lo podríamos poner aquí.
Esto es una función asíncrona.
El LoginService lo vamos a tener que importar.
Pues lo importamos.
Services, Login.
Vale, el Username y Password le van a llegar por parámetro.
Vale, vale.
Este SetUser tiene sentido porque es dentro del propio CustomHook que queremos cambiar,
que ahora tenemos un usuario, cambiar el estado, lo devolveremos.
Y aquí ya tendríamos, si vamos a Notas, esta parte de aquí ahora debería ser el Login.
No del servicio, porque me trae el servicio, no servicio, sino que sería del, aquí tendríamos User, Login y Logout.
Y esto lo haríamos de ese UseUser.
Como tal, esto no lo necesitamos ya.
El UseUser lo tenemos que importar.
HooksUser.js
Estamos haciendo un Export.
Vale, perfecto.
Vamos a ver dónde tendríamos que utilizar cada uno.
Este efecto ya no lo necesitamos porque justamente esto lo hace el CustomHook,
así que esto lo podemos eliminar.
El HandleLogout, esto lo que tiene que hacer es simplemente llamar a Logout,
que ya está haciendo todo esto.
De hecho, este HandleLogout podríamos hacerlo, podríamos llamarlo directamente,
pero ahora lo voy a dejar así.
Aquí en el HandleLogin, pues sería llamar al Login y pasarle el Username y el Password.
Y todo esto lo podemos dejar justamente aquí.
Y ahora con esto, pues ya deberíamos tenerlo todo.
Mira, ya ni siquiera necesitamos el NodeService, tampoco necesitamos un UseEffect.
Fíjate, ya vemos las notas que no tiene ningún UseEffect.
O sea, lo hemos limpiado en un momento y hemos hecho que no tenga ningún UseEffect.
Tal cual, pam, de una.
Así que ya ves que aquí en el UseUser, pues hemos hecho uno que sea con AsyncAwait,
pero también podéis hacer que devuelva promesas.
Al final esto no es importante como tal, ¿vale?
Vamos a probarlo, ¿vale?
NodesUsers, vamos a eliminar.
Voy a eliminar el Application, ClearSetDight, ¿vale?
Cuando hago Login, ¿vale?
Aparecen las notas y está funcionando todo correctamente.
Así que, pues con esto ahora tenemos en un CustomHook todo lo que tiene que ver con el usuario,
en otro todo lo que tiene que ver con las notas,
y en el componente notas lo único que hemos dejado es utilizar, pues nada,
el UseNotes y el UseUser.
Este UseUser, además, claro, ahora que lo tenemos así,
incluso podríamos intentar pasarlo más abajo,
en lugar de ver si tiene sentido realmente que se utilice aquí o más abajo,
ver más cosas.
Pero por ahora podríamos tenerlo un poco así.
También, obviamente, una cosa que es interesante porque a lo mejor ahora en el UseCounter
y en estos ejemplos nos hemos enfocado mucho en el tema de que sea lógica de tu aplicación, ¿vale?