Quels sont les hooks dans React?
sobes.tech IA
Réponse de l'IA
En React, à partir de la version 16.8, los hooks permiten a los componentes funcionales gestionar el estado y usar ciclos de vida, que anteriormente solo estaban disponibles para componentes de clase.
Aquí están los hooks integrados principales:
-
useState: Permite agregar estado interno a un componente funcional. Devuelve una pareja: el estado actual y una función para actualizarlo.// Ejemplo useState import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); // Inicialización del estado con 0 return ( <div> <p>Vous avez cliqué {count} fois</p> <button onClick={() => setCount(count + 1)}> Clique moi </button> </div> ); } -
useEffect: Permite realizar efectos secundarios en componentes funcionales. Similar a los métodos del ciclo de vida de componentes de clase (componentDidMount,componentDidUpdate,componentWillUnmount).// Ejemplo useEffect import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // Se ejecuta después de cada renderizado useEffect(() => { document.title = `Vous avez cliqué ${count} fois`; }); // Solo se ejecuta en el primer renderizado (matriz de dependencias vacía) useEffect(() => { console.log('Composant monté'); return () => { console.log('Composant démonté'); // Función de limpieza }; }, []); // Se ejecuta al cambiar count useEffect(() => { console.log('Count a changé:', count); }, [count]); return ( <div> <p>Vous avez cliqué {count} fois</p> <button onClick={() => setCount(count + 1)}> Clique moi </button> </div> ); } -
useContext: Permite suscribirse a los cambios del contexto de React. Toma un objeto de contexto creado conReact.createContext().// Ejemplo useContext import React, { useContext } from 'react'; const ThemeContext = React.createContext('light'); // Creación del contexto function ThemedButton() { const theme = useContext(ThemeContext); // Uso del contexto return ( <button className={theme}> Botón en tema {theme} </button> ); } function App() { return ( <ThemedButton /> ); } -
useReducer: Alternativa auseStatepara gestionar estados más complejos, que incluyen múltiples subvalores o cuando el siguiente estado depende del anterior. Similar a los reductores en Redux.// Ejemplo useReducer import React, { useReducer } from 'react'; const initialState = { count: 0 }; function reducer(state, action) { switch (action.type) { case 'increment': return { count: state.count + 1 }; case 'decrement': return { count: state.count - 1 }; default: throw new Error(); } } function Counter() { const [state, dispatch] = useReducer(reducer, initialState); return ( <> Count: {state.count} <button onClick={() => dispatch({ type: 'increment' })}>+</button> <button onClick={() => dispatch({ type: 'decrement' })}>-</button> </> ); } -
useCallback: Memoise una función de callback. Devuelve una versión memorizada del callback que solo cambia si cambia alguna de las dependencias. Es útil para evitar renderizados innecesarios de componentes hijos al pasar callbacks.// Ejemplo useCallback import React, { useState, useCallback } from 'react'; function Parent({ addTodo }) { const [count, setCount] = useState(0); const handleAddTodo = useCallback(() => { addTodo(); }, [addTodo]); // Dependencia de addTodo return ( <> <button onClick={() => setCount(count + 1)}> Incrementar contador </button> <Child onAddItem={handleAddTodo} /> </> ); } function Child({ onAddItem }) { console.log('Child renderiza'); // Solo renderiza cuando onAddItem cambia return <button onClick={onAddItem}>Agregar elemento</button>; } -
useMemo: Memoiza un valor calculado. Devuelve un valor memorizado que solo se recalcula si cambia alguna de las dependencias. Útil para mejorar el rendimiento en cálculos costosos.// Ejemplo useMemo import React, { useMemo, useState } from 'react'; function expensiveCalculation(num) { console.log('Ejecutando cálculo costoso...'); for (let i = 0; i < 1000000; i++) { num += 1; } return num; } function Example() { const [count, setCount] = useState(0); const [todos, setTodos] = useState([]); const calculation = useMemo(() => expensiveCalculation(count), [count]); // Dependencia de count const addTodo = () => { setTodos(t => [...t, "Nuevo Todo"]); }; return ( <div> <div> <h2>Mis Todo</h2> {todos.map((todo, index) => ( <p key={index}>{todo}</p> ))} <button onClick={addTodo}>Agregar Todo</button> </div> <hr /> <div> Contador: {count} <button onClick={() => setCount(c => c + 1)}>+</button> <h2>Cálculo costoso</h2> {calculation} </div> </div> ); } -
useRef: Permite crear una referencia mutable que persiste durante toda la vida del componente. Se usa comúnmente para acceder a elementos DOM o almacenar cualquier valor mutable que no cause renderizado al cambiar.// Ejemplo useRef import React, { useRef } from 'react'; function TextInputWithFocusButton() { const inputEl = useRef(null); // Crear referencia const onButtonClick = () => { // current apunta al elemento DOM montado inputEl.current.focus(); }; return ( <> <input ref={inputEl} type="text" /> // Asignar referencia <button onClick={onButtonClick}>Enfocar campo de entrada</button> </> ); } -
useImperativeHandle: Configura el descriptor del instancia que se expone al componente padre cuando se usaref. Permite que el componente hijo exponga ciertos métodos al componente padre. Se usa junto conforwardRef.// Ejemplo useImperativeHandle import React, { useRef, useImperativeHandle, forwardRef } from 'react'; const MyInput = forwardRef((props, ref) => { const inputRef = useRef(); useImperativeHandle(ref, () => ({ focusInput: () => { inputRef.current.focus(); } })); return <input ref={inputRef} {...props} />; }); function ParentComponent() { const inputRef = useRef(); const handleFocus = () => { inputRef.current.focusInput(); // Llamada a método del componente hijo }; return ( <div> <MyInput ref={inputRef} /> <button onClick={handleFocus}>Enfocar desde Parent</button> </div> ); } -
useLayoutEffect: Igual queuseEffect, pero se ejecuta sincrónicamente después de todas las mutaciones del DOM. Útil para leer datos del DOM o hacer mutaciones que deben ocurrir antes de que el navegador repinte la pantalla. Puede bloquear el renderizado.// Ejemplo useLayoutEffect import React, { useLayoutEffect, useRef } from 'react'; function Tooltip({ children, text }) { const ref = useRef(null); useLayoutEffect(() => { if (ref.current) { // Cálculos basados en el DOM antes del repintado const { top, height } = ref.current.getBoundingClientRect(); console.log(`El elemento está en ${top} con altura ${height}`); } }, [children]); return ( <span ref={ref} title={text}> {children} </span> ); } -
useDebugValue: Muestra una etiqueta personalizada para los hooks en React DevTools. Se usa en hooks personalizados para depuración.// Ejemplo useDebugValue import React, { useState, useDebugValue } from 'react'; function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); // Muestra 'Friend Status: Offline' o 'Friend Status: Online' en DevTools useDebugValue(isOnline === true ? 'Online' : 'Offline'); // ... lógica para obtener el estado del amigo return isOnline; } function FriendListItem({ friend }) { const isOnline = useFriendStatus(friend.id); return ( <li style={{ color: isOnline ? 'green' : 'black' }}> {friend.name} - {isOnline ? 'En línea' : 'Desconectado'} </li> ); }
Además de los hooks integrados, existen hooks personalizados (Custom Hooks). Son funciones JavaScript que comienzan con "use". Permiten reutilizar lógica de estado entre componentes. Un hook personalizado puede llamar a otros hooks.
// Ejemplo de hook personalizado
import { useState, useEffect } from 'react';
function useWindowSize() {
const [size, setSize] = useState([window.innerWidth, window.innerHeight]);
useEffect(() => {
const handleResize = () => {
setSize([window.innerWidth, window.innerHeight]);
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
return size;
}
function MyComponent() {
const [width, height] = useWindowSize(); // Uso del hook personalizado
return (
<p>Dimensiones de la ventana: {width}x{height}</p>
);
}
Es importante seguir las Reglas de los Hooks:
- Llamar a los hooks solo en el nivel superior de componentes React o hooks personalizados. No llamarlos dentro de bucles, condiciones o funciones anidadas.
- Llamar a los hooks solo desde componentes funcionales de React o hooks personalizados. No llamarlos desde funciones JavaScript normales o métodos de componentes de clase.