Skip to content

Instantly share code, notes, and snippets.

@dbritto-dev
Last active June 24, 2021 16:13
Show Gist options
  • Select an option

  • Save dbritto-dev/aebd0d8b35e079f3c92b2f7b6fc487f2 to your computer and use it in GitHub Desktop.

Select an option

Save dbritto-dev/aebd0d8b35e079f3c92b2f7b6fc487f2 to your computer and use it in GitHub Desktop.
React Hooks para principiantes
import { useCallback } from 'react'
// Hook: useCallback
const callbackMemoizado = useCallback(() => {
// contenido de tu función de retorno (callback)
}, [...dependencias])
// Usos de useCallback
// Podemos usar useCallback para crear una función que se
// cree unicamente cuando alguna de sus dependencias sufra algun cambio
// o se actualize, debido a que pasaremos dicha función a otro componente
// y no queremos que se renderize a causa de que la funcion se re-cree
// como conscuencia de los eventos que ocurran en el componente, de esta manera
// podremos evitar que el componente hijo al que le pasemos dicha función
// se renderize innecesariamente.
// Por ejemplo: imaginemos que queremos crear una función que luego usaremos
// para construir una consulta que se usará posteriormentet para traer cierta información
// usando como dependencia un servicio que se crea dinámicamente.
const getPlaceQuery = useCallback(() => createQuery(service), [service])
<ChildComponent getPlaceQuery={getPlaceQuery} />
import { useContext, createContext } from 'react'
// Hook: useContext
// Context API: createContext()
const SomeContext = createContext()
const valueToSharedAcrossAllComponents = {
someData: 'Some data to share'
};
const Provider = ({ children }) => {
return (
<SomeContext.Provider value={valueToSharedAcrossAllComponents}>
{children}
</SomeContext.Provider>
)
}
const useSomeContext = () => {
const someContext = useContext(SomeContext);
if (someContext === undefined) {
throw new Error(`useSomeContext debe ser usando dentro de Provider`)
}
return someContext;
}
// Usos del useContext y Context API
// Podemos usar useContext y Context API para enviar cierta información
// que queremos compartir en varios componentes que no se encuentran en
// el mismo nivel o padre.
// Por ejemplo: si queremos compartir el tema de la aplicación a todos los
// componentes de la aplicación.
const theme = { color: 'peru', fontFamily: 'Roboto' }
const ThemeContext = createContext()
const ThemeProvider = ({ theme, children }) => {
return <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>
}
const useTheme = () => {
const theme = useContext(ThemeContext);
if (theme === undefined) {
throw new Error(`useTheme debe ser usando dentro de ThemeProvider`)
}
return theme;
}
import { useEffect } from 'react'
// Hook: useEffect
useEffect(() => {
// Ejecuta esto:
// 1. cuando el component se monta -> `componentDidMount()`
// 2. cuando la `informacion` se actualiza -> `componentDidUpdate()`
return () => {
// Ejecuta esto:
// 1. cuando la `informacion` se actualiza -> `componentDidUpdate()`
// 2. cuando el componente se va a desmontar -> `componentWillUnmount()`
}
}, [informacion])
// Usos del useEffect
// Cuando el hook `useEffect` no tiene definida una lista de dependencias
// significa estara pendiente de todos los cambios que sufra el componente
// internamente (a causa de alguna actualización en los estados que maneja
// internamente) o externamente (a causa de alguna actualizacion en las
// propiedades que se le pasa al componente cuando es utilizado).
useEffect(() => {
// `componentDidMunt()` + `componentDidUpdate()`
return () => {} // `componentDidUpdate()` + `componentWilUnmount()`
})
// Cuando el hook `useEffect` tiene definida una lista de dependencias
// pero dicha lista es esta vacia, significa que solo estará pendiente
// a que el componente sea montado.
useEffect(() => {
// `componentDidMunt()` + `componentDidUpdate()`
return () => {} // `componentDidUpdate()` + `componentWilUnmount()`
}, [])
// ✍️ Nota: la función anonima que le pasemos a useEffect no puede ser
// asíncrona, por lo que si deseamos ejecutar una función asíncrona
// es necesario crear dicha función dentro y luego usarla como en el siguiente ejemplo.
useEffect(() => {
const getDataAsync = async () => {}
getDataAsync()
}, [])
// Cuando el hook `useEffect` tiene definida una lista de dependencias
// significa que estará pendiente de los cambios que cualquiera de las
// dependencias tenga de tal manera que la mantendra sincronizada.
useEffect(() => {
// `componentDidMunt()` + `componentDidUpdate()`
return () => {} // `componentDidUpdate()` + `componentWilUnmount()`
}, [...dependencias])
// ✍️ Nota: Es importante declarar la lista de dependencias al definir el useEffect
// y no usar declarar afuera y asignarle el valor al `useEffect` como en el
// siguiente ejemplo:
const dependencias = [primeraDependencia, segundaDependencia, terceraDependencia] ❌
useEffect(() => {}, dependencias) ❌
// crear la lista de dependencias como parte del `useEffect`
useEffect(() => {}, [primeraDependencia, segundaDependencia, terceraDependencia]) ✔️
// ✨ Tip: podemos cargar información dinámicamente usando como dependencia el valor
// de algun dato que necesitemos para cargar la información. Un ejemplo puede ser que
// necesitemos cargar los datos del usuario según el identificador del usuario, como
// haremos en el siguiente ejemplo:
useEffect(() => {
const getDataAsync = async () => {
try {
const response = await fetch(`http://awesome.api/user/${userId}/`)
const data = response.json()
} catch(e) {
window.alert(`Error: Ha ocurrido un error al intentar cargar los datos del usuario: ${userId}`)
}
}
getDataAsync()
}, [userId])
import { useMemo } from 'react'
// Hook: useMemo
useMemo(() => procesosPesados(), [...dependencias])
// Usos del useMemo
// Podemos usar useMemo para evitar ejecutar procesos pesados o calculos
// pesados: filtrar, ordenar, fibonacci, etc.
// usuarios y queremos devolver solo los usuarios cuyo estado es 3
const usuariosFiltrados = useMemo(
() => usuarios.filter(usuario => usuario.status == 3),
[usuarios]
)
import { useReducer } from 'react'
// Hook: useReducer
const [estado, disparador] = useReducer((estado, accion) => {
// Codigo para calcular el nuevo estado basado en la acción
// nuevoEstado = f(estado, accion)
}, estadoInicial)
// ✍️ Nota: el estado inicial no necesariamente tiene que ser un objecto
// Usos del useReducer
// Podemos usar useReducer usando conocimientos previos de redux
// debido a que useReducer usa una función para calcular el nuevo
// estado tal y cual lo hace redux.
// Por ejemplo: imaginemos que queremos crear un contador usando
// useReducer para delimitar y tener mas control sobre las acciones
// permitidas para interactuar con el estado.
const [state, dispatch] = useReducer((state, action) => {
switch(action.type) {
case 'INCREMENT': {
return state + 1;
}
case 'DECREMENT': {
return state - 1:
}
default: {
throw new Error(`The ${action.type} is not permitted.`)
}
}
}, 0)
// Ahora podemos usar `dispatch` para trabajar sobre nuestro contador
dispatch({ type: 'INCREMENT' })
console.log(state)
dispatch({ type: 'INCREMENT' })
console.log(state)
dispatch({ type: 'DECREMENT' })
console.log(state)
// ✨ Tip: podemos reemplazar la mayoria de casos de uso de redux para
// la gestion de estados locales (dentro del component) y externos mediante
// el uso de useContext y Context API.
import { useState } from 'react'
// Hook: useState
const [estado, definirEstado] = useState(estadoInicial)
// Usos del useState
// Podemos manejar multiples estados y utilizar dichos estados
// como el estado inicial de otro estado
const [firstName, setFirstName] = useState('')
const [lastName, setLastName] = useState('')
const [fullName, setFullName] = useState(`${lastName}, ${firstName}`)
// ✍️ Nota: cuando el valor a actualizar es generado a partir del estado actual
// es mejor usar una funcion para definir el siguiente estado. Por ejemplo:
// Cuando creamos un contador usamos el estado anterior para calcular el
// siguiente estado: estado -> contador = contador + 1
// Por lo que la forma correcta es definir el estado es mediante una función
// de tal manera de que nos aseguremos que estamos usando el último estado.
const [count, setCount] = useState(0)
// No es seguro usar el estado fuera del metodo del metodo para actualizar el estado
// si es que queremos calcular el nuevo estado basado en el estado actual.
setCount(count + 1) ❌
// ✨ Tip: podemos pasar una función como parametro el cual recibe el estado actual,
// por lo tanto podemos calcular el siguiente estado de forma segura.
setCount(currentCount => currentCount + 1) ✔️
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment