Hooks ⚛️
- Autor
- Name
- Anibal Santos
- Publicado
- Lectura
- 4 '
En este capítulo vamos a hablar acerca de los hooks en React.
¿Qué son los hooks?
Los hooks
son funciones que enganchan el estado y el ciclo de vida de un componente. No funcionan con componentes de clases.
useState
import { useState } from 'react'const CountButton = () => { const [count, setCount] = useState(0) return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}>Click me</button> </div> )}
useState
: declara la variable estado. El argumento que recibe es el valor inicial del estado.count
: es la variable para leer el valor actual del estado.setCount
: es la función que actualiza el valor del estado.
useEffect
Incluye la lógica de métodos componentDidUpdate
, componentDidMount
y componentWillUnmount
import { useEffect } from 'react'useEffect(() => { // se ejecuta la lógica del mount y el update, como por ejemplo fetching data})
import { useEffect } from 'react'useEffect(() => { // se ejecuta la lógica del mount y el update, como por ejemplo fetching data return () => { // se ejecuta la lógica del unmount (limpiar, cancelar timers, suscripciones) }}, [])
import { useEffect } from 'react'const Component = (props) => { useEffect(() => { // la lógica es ejecutada cuando ALGUNA de las variables cambia }, [arrOfDependency, values, props.id])}
useState
& useEffect
Essential hooks: import { useEffect, useState } from 'react'const ComponentWithHooks = () => { const [projectId, setProjectId] = useState(0) const [versionId, setVersionId] = useState(0) useEffect(() => { getComments() }, []) useEffect(() => { getGeneralData(projectId, versionId) getIndicators(projectId, versionId) }, [projectId, versionId])}
Otros Hooks
useReducer
Se utiliza para realizar una gestión del estado avanzada. Es parecido al concepto de reducer
en Redux, Vuex, NGRX.
Es una forma de ordenar un estado complejo.
const [state, dispatch] = useReducer(reducer, { count: initialCount })
useCallback
Nos memoriza una función, es una forma de cachear funciones, a no ser que cambie a
o b
, no se vuelve a ejecutar dicha función. Por lo tanto podemos utilizarlo si no queremos estar definiendo constantemente una función.
const memoizedCallback = useCallback(() => { doSomething(a, b)}, [a, b])
useMemo
Nos memoriza un valor, es una forma de cachear valores, a no ser que cambie a
o b
, no se vuelve a ejecutar la función. Es útil cuando tenemos por ejemplo un cálculo de algo costoso.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b])
useRef
Genera referencias de elementos, variables, elementos del DOM... para tenerlos accesibles.
const refImg = useRef(initialValue);<img ref={refImg}>
Cómo refactorizar componente de clase a componente funcional:
import { useEffect } from 'react'const Header = (props) => { useEffect(() => { window.alert('mount') }, []) useEffect(() => { // Realmente habría que hacerlo con un useRef en un custom hook if (props.title !== 'React Training') { window.alert('update') } }, [props.title]) return ( <header onClick={props.onClick}> <h1>{props.title}</h1> <nav> <ul> <li>Option 1</li> <li>Option 2</li> <li>Option 3</li> <li>Option 4</li> </ul> </nav> </header> )}
const App = () => { const [title, setTitle] = useState('React Training') const handleHeaderClick = () => { setTitle(`${title} Classes`) } return ( <div> <Header title={title} handleClick={handleHeaderClick} />; </div> )}
Realmente no es usual que tengamos el caso de componentDidMount
y componentDidUpdate
en useEffect
, algo más aproximado a la vida real sería el siguiente ejemplo:
import { useEffect, useState } from 'react'const getData = () => new Promise((res) => setTimeout(() => { res({ title: 'New Title' }) }, 2000) )const Header = (props) => { const [data, setData] = useState({ title: null }) useEffect(() => { getData(props.title).then((res) => setData(res)) }, [props.title]) return ( <header onClick={props.onClick}> <h1>{props.title}</h1> <nav> <ul> <li>Option 1</li> <li>Option 2</li> <li>Option 3</li> <li>Option 4</li> </ul> </nav> </header> )}
const App = () => { const [title, setTitle] = useState('React Training') const handleHeaderClick = () => { setTitle(`${title} Classes`) } return ( <div> <Header title={title} handleClick={handleHeaderClick} />; </div> )}
Custom Hooks
Partiendo del ejemplo anterior vamos a ver un ejemplo de custom hook:
import { useEffect, useState } from 'react'const getData = () => new Promise((res) => setTimeout(() => { res({ title: 'New Title' }) }, 2000) )const useData = (tile) => { const [data, setData] = useState({ title: null }) useEffect(() => { getData(title).then((res) => setData(res)) }, [title]) return [data, setData]}const Header = (props) => { const [data, setData] = useData(props.title) return ( <header> <h1 onClick={props.onClick}>{data.title}</h1> <nav> <ul> <li onClick={() => setData({ title: 'Option 1' })}>Option 1</li> <li>Option 2</li> <li>Option 3</li> <li>Option 4</li> </ul> </nav> </header> )}
const App = () => { const [title, setTitle] = useState('React Training') const handleHeaderClick = () => { setTitle(`${title} Classes`) } return ( <div> <Header title={title} handleClick={handleHeaderClick} />; </div> )}
Aplicar custom hooks nos permite reutilizar código y sacar algo de lógica de los componentes. Básicamente está compuesto por otros hooks:
const useData = (tile) => { const [data, setData] = useState({ title: null }) useEffect(() => { getData(title).then((res) => setData(res)) }, [title]) return [data, setData]}
❤️ Espero que te haya gustado la entrada.
Puedes continuar leyendo el siguiente capítulo sobre Conceptos avanzados, volver al capítulo anterior de Class components, o volver al Índice.