Top 100 Preguntas Completas de React
Las 100 Preguntas Completas de React
Section titled “Las 100 Preguntas Completas de React”Esta guía cubre desde fundamentos hasta temas avanzados. Las preguntas 1-50 están en las guías anteriores.
Estado Global y Gestión de Estado (51-65)
Section titled “Estado Global y Gestión de Estado (51-65)”51. ¿Qué es Redux y cuándo usarlo?
Section titled “51. ¿Qué es Redux y cuándo usarlo?”¿Qué es? Librería de gestión de estado global con flujo unidireccional: Action → Reducer → Store → View.
¿Cuándo usarlo?
- Estado compartido entre muchos componentes
- Lógica de estado compleja
- Necesitas debugging avanzado (time-travel)
// Storeconst store = createStore(rootReducer);
// Reducerfunction counterReducer(state = { count: 0 }, action) {switch (action.type) { case 'INCREMENT': return { count: state.count + 1 }; default: return state;}}
// Dispatchstore.dispatch({ type: 'INCREMENT' });52. ¿Qué es Redux Toolkit?
Section titled “52. ¿Qué es Redux Toolkit?”¿Qué es? La forma oficial y moderna de usar Redux. Reduce el boilerplate significativamente.
Incluye: createSlice (reducer + actions), configureStore (setup automático), Immer (mutaciones inmutables).
import { createSlice, configureStore } from '@reduxjs/toolkit';
const counterSlice = createSlice({name: 'counter',initialState: { value: 0 },reducers: { increment: (state) => { state.value += 1; // Immer permite mutación }, incrementByAmount: (state, action) => { state.value += action.payload; }}});
export const { increment, incrementByAmount } = counterSlice.actions;
const store = configureStore({reducer: { counter: counterSlice.reducer}});53. ¿Qué es Zustand?
Section titled “53. ¿Qué es Zustand?”¿Qué es? Librería de estado global minimalista. Solo 1KB, sin boilerplate, basada en hooks.
¿Para qué sirve? Alternativa simple a Redux cuando no necesitas toda su complejidad.
import { create } from 'zustand';
const useStore = create((set) => ({count: 0,increment: () => set((state) => ({ count: state.count + 1 })),decrement: () => set((state) => ({ count: state.count - 1 })),reset: () => set({ count: 0 })}));
// Uso en componentefunction Counter() {const { count, increment } = useStore();return <button onClick={increment}>{count}</button>;}54. ¿Qué es Jotai?
Section titled “54. ¿Qué es Jotai?”¿Qué es? Librería de estado atómico. Cada pieza de estado es un “atom” independiente.
¿Para qué sirve? Estado granular sin re-renders innecesarios. Ideal para estado derivado.
import { atom, useAtom } from 'jotai';
// Atoms - unidades de estadoconst countAtom = atom(0);const doubleAtom = atom((get) => get(countAtom) * 2);
function Counter() {const [count, setCount] = useAtom(countAtom);const [double] = useAtom(doubleAtom);
return ( <div> <p>{count} (double: {double})</p> <button onClick={() => setCount(c => c + 1)}>+</button> </div>);}55. ¿Qué es Recoil?
Section titled “55. ¿Qué es Recoil?”¿Qué es? Librería de estado atómico creada por Facebook. Similar a Jotai pero con más features.
Conceptos: atom (estado), selector (estado derivado), keys únicos obligatorios.
import { atom, selector, useRecoilState, useRecoilValue } from 'recoil';
const textState = atom({key: 'textState',default: ''});
const charCountState = selector({key: 'charCountState',get: ({ get }) => get(textState).length});
function CharacterCount() {const count = useRecoilValue(charCountState);return <p>Caracteres: {count}</p>;}56. ¿Cuál es la diferencia entre Redux, Zustand, Jotai y Recoil?
Section titled “56. ¿Cuál es la diferencia entre Redux, Zustand, Jotai y Recoil?”Resumen: Redux es robusto pero complejo. Zustand es simple. Jotai/Recoil son atómicos (estado granular).
| Característica | Redux | Zustand | Jotai | Recoil |
|---|---|---|---|---|
| Boilerplate | Alto | Bajo | Bajo | Medio |
| DevTools | Excelente | Bueno | Bueno | Bueno |
| Bundle size | Grande | Pequeño | Pequeño | Medio |
| Curva aprendizaje | Alta | Baja | Baja | Media |
| Patrón | Flux | Flux-like | Atómico | Atómico |
57. ¿Qué es React Query / TanStack Query?
Section titled “57. ¿Qué es React Query / TanStack Query?”¿Qué es? Librería para manejar “server state” (datos del servidor). NO es para estado local.
¿Para qué sirve? Caching, refetch automático, loading/error states, invalidación, paginación.
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
function Posts() {const { data, isLoading, error } = useQuery({ queryKey: ['posts'], queryFn: () => fetch('/api/posts').then(res => res.json())});
const queryClient = useQueryClient();
const mutation = useMutation({ mutationFn: (newPost) => fetch('/api/posts', { method: 'POST', body: JSON.stringify(newPost) }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['posts'] }); }});
if (isLoading) return <Loading />;if (error) return <Error />;
return <PostList posts={data} />;}58. ¿Qué es SWR?
Section titled “58. ¿Qué es SWR?”¿Qué es? Librería de Vercel para data fetching. Nombre viene de “stale-while-revalidate”.
¿Para qué sirve? Similar a React Query pero más simple. Ideal para proyectos Next.js.
import useSWR from 'swr';
const fetcher = (url) => fetch(url).then(res => res.json());
function Profile() {const { data, error, isLoading, mutate } = useSWR('/api/user', fetcher);
// Revalidar manualmenteconst refresh = () => mutate();
// Actualización optimistaconst updateName = async (newName) => { mutate({ ...data, name: newName }, false); await fetch('/api/user', { method: 'PUT', body: JSON.stringify({ name: newName }) }); mutate();};
if (isLoading) return <Loading />;return <div>{data.name}</div>;}59. ¿Cuándo usar React Query vs Redux?
Section titled “59. ¿Cuándo usar React Query vs Redux?”Regla simple: React Query para datos del servidor, Redux para estado de la UI.
| React Query | Redux |
|---|---|
| Server state | Client state |
| Caching automático | Cache manual |
| Refetch automático | Manual |
| Datos remotos | Datos locales |
60. ¿Qué es el patrón de estado derivado?
Section titled “60. ¿Qué es el patrón de estado derivado?”¿Qué es? Calcular valores a partir de otro estado en vez de duplicar.
Regla: Si un valor puede calcularse de otro, NO lo guardes en estado separado.
// MAL - duplicar estadoconst [items, setItems] = useState([]);const [filteredItems, setFilteredItems] = useState([]); // Duplicado
// BIEN - derivar estadoconst [items, setItems] = useState([]);const [filter, setFilter] = useState('');
const filteredItems = useMemo(() =>items.filter(item => item.name.includes(filter)),[items, filter]);61. ¿Qué es el patrón de estado normalizado?
Section titled “61. ¿Qué es el patrón de estado normalizado?”¿Qué es? Estructurar estado como base de datos: entidades separadas con IDs como referencias.
¿Para qué sirve? Evitar duplicación, facilitar actualizaciones, mejor performance.
// Desnormalizado (evitar)const state = {posts: [ { id: 1, author: { id: 1, name: 'Juan' }, comments: [...] }]};
// Normalizado (preferido)const state = {posts: { byId: { 1: { id: 1, authorId: 1, commentIds: [1, 2] } }, allIds: [1]},users: { byId: { 1: { id: 1, name: 'Juan' } }, allIds: [1]},comments: { byId: { 1: {...}, 2: {...} }, allIds: [1, 2]}};62. ¿Cómo persistir estado?
Section titled “62. ¿Cómo persistir estado?”¿Qué es? Guardar estado en localStorage/sessionStorage para que sobreviva recargas de página.
¿Cómo? Usar middleware de persistencia (Zustand, Redux Persist) o custom hooks.
// Con Zustandimport { persist } from 'zustand/middleware';
const useStore = create(persist( (set) => ({ count: 0, increment: () => set((state) => ({ count: state.count + 1 })) }), { name: 'counter-storage', storage: createJSONStorage(() => localStorage) }));63. ¿Qué es el patrón de selectors?
Section titled “63. ¿Qué es el patrón de selectors?”¿Qué es? Funciones que extraen y transforman datos del estado global.
¿Para qué sirve? Encapsular lógica de acceso, memoizar cálculos, desacoplar componentes del shape del estado.
// Selector - función que extrae datos del estadoconst selectTodos = (state) => state.todos;const selectCompletedTodos = (state) =>state.todos.filter(todo => todo.completed);
// Con reselect (memoizado)import { createSelector } from 'reselect';
const selectCompletedTodos = createSelector([selectTodos],(todos) => todos.filter(todo => todo.completed));64. ¿Qué es middleware en Redux?
Section titled “64. ¿Qué es middleware en Redux?”¿Qué es? Funciones que interceptan actions antes de llegar al reducer.
¿Para qué sirve? Logging, async operations, analytics, validaciones.
// Middleware personalizadoconst loggerMiddleware = (store) => (next) => (action) => {console.log('Dispatching:', action);const result = next(action);console.log('Next state:', store.getState());return result;};
// Configurarconst store = configureStore({reducer: rootReducer,middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(loggerMiddleware)});65. ¿Qué es Redux Thunk vs Redux Saga?
Section titled “65. ¿Qué es Redux Thunk vs Redux Saga?”Thunk: Middleware simple para async. Actions pueden ser funciones.
Saga: Middleware avanzado con generators. Para flujos complejos (cancelación, retry, race conditions).
// Thunk - funciones async simplesconst fetchUser = (id) => async (dispatch) => {dispatch({ type: 'FETCH_START' });try { const user = await api.getUser(id); dispatch({ type: 'FETCH_SUCCESS', payload: user });} catch (error) { dispatch({ type: 'FETCH_ERROR', error });}};
// Saga - generators para flujos complejosfunction* fetchUserSaga(action) {try { const user = yield call(api.getUser, action.payload); yield put({ type: 'FETCH_SUCCESS', payload: user });} catch (error) { yield put({ type: 'FETCH_ERROR', error });}}React 18+ Features (66-80)
Section titled “React 18+ Features (66-80)”66. ¿Qué es Automatic Batching?
Section titled “66. ¿Qué es Automatic Batching?”¿Qué es? React 18 agrupa múltiples actualizaciones de estado en UN solo re-render.
Antes (React 17): Solo en event handlers. Ahora: En todas partes (setTimeout, promises, etc.).
// React 17 - solo batching en event handlers// React 18 - batching automático en todas partes
function handleClick() {setCount(c => c + 1);setFlag(f => !f);// React 18: un solo re-render}
// Incluso en asyncsetTimeout(() => {setCount(c => c + 1);setFlag(f => !f);// React 18: un solo re-render}, 1000);
// Para forzar render inmediatoimport { flushSync } from 'react-dom';flushSync(() => setCount(c => c + 1));67. ¿Qué son los Server Components?
Section titled “67. ¿Qué son los Server Components?”¿Qué es? Componentes que se ejecutan SOLO en el servidor. No se envían al cliente.
Beneficios: Acceso directo a BD, bundle más pequeño, mejor SEO, datos sensibles seguros.
// Server Component (por defecto en Next.js 13+)// - Se ejecuta en el servidor// - No tiene estado ni efectos// - Puede acceder directamente a BD
async function Posts() {const posts = await db.posts.findMany();return ( <ul> {posts.map(post => <li key={post.id}>{post.title}</li>)} </ul>);}
// Client Component'use client';
function Counter() {const [count, setCount] = useState(0);return <button onClick={() => setCount(c => c + 1)}>{count}</button>;}68. ¿Cuál es la diferencia entre Server y Client Components?
Section titled “68. ¿Cuál es la diferencia entre Server y Client Components?”Regla simple: Server por defecto, Client solo cuando necesitas interactividad (estado, eventos, hooks de browser).
| Server Components | Client Components |
|---|---|
| Se ejecutan en servidor | Se ejecutan en cliente |
| Sin estado/efectos | Con estado/efectos |
| Acceso directo a BD | Fetch API |
| No incluidos en bundle | Incluidos en bundle |
| Por defecto | Requieren ‘use client’ |
69. ¿Qué es Streaming SSR?
Section titled “69. ¿Qué es Streaming SSR?”¿Qué es? Enviar HTML progresivamente mientras se renderiza, en vez de esperar a que todo esté listo.
Beneficio: El usuario ve contenido más rápido. Suspense muestra fallbacks mientras carga.
// Permite enviar HTML progresivamenteimport { Suspense } from 'react';
function Page() {return ( <div> <Header /> {/* Se envía inmediatamente */}
<Suspense fallback={<PostsSkeleton />}> <Posts /> {/* Se envía cuando esté listo */} </Suspense>
<Suspense fallback={<CommentsSkeleton />}> <Comments /> {/* Se envía cuando esté listo */} </Suspense> </div>);}70. ¿Qué es el hook use?
Section titled “70. ¿Qué es el hook use?”¿Qué es? Hook de React 19 que puede leer promises y context directamente.
¿Para qué sirve? Simplificar data fetching con Suspense. Puede usarse condicionalmente (a diferencia de otros hooks).
// React 19 - hook use para promises y contextimport { use } from 'react';
function Comments({ commentsPromise }) {// Suspende hasta que la promise resuelvaconst comments = use(commentsPromise);
return comments.map(c => <Comment key={c.id} {...c} />);}
// También para contextfunction Theme() {const theme = use(ThemeContext);return <div style={{ color: theme.color }}>...</div>;}71. ¿Qué son las Server Actions?
Section titled “71. ¿Qué son las Server Actions?”¿Qué es? Funciones asíncronas que se ejecutan en el servidor, llamadas desde el cliente.
¿Para qué sirve? Mutaciones de datos sin crear API routes. Se marcan con 'use server'.
// Server Action - función que se ejecuta en servidorasync function createPost(formData) {'use server';
const title = formData.get('title');await db.posts.create({ data: { title } });revalidatePath('/posts');}
// Uso en componentefunction NewPostForm() {return ( <form action={createPost}> <input name="title" /> <button type="submit">Crear</button> </form>);}72. ¿Qué es useFormStatus?
Section titled “72. ¿Qué es useFormStatus?”¿Qué es? Hook que da información sobre el estado de un form padre (pending, data, method, action).
¿Para qué sirve? Mostrar loading en botones de submit mientras el form se procesa.
'use client';import { useFormStatus } from 'react-dom';
function SubmitButton() {const { pending } = useFormStatus();
return ( <button type="submit" disabled={pending}> {pending ? 'Enviando...' : 'Enviar'} </button>);}73. ¿Qué es useFormState?
Section titled “73. ¿Qué es useFormState?”¿Qué es? Hook que maneja estado basado en el resultado de una Server Action.
¿Para qué sirve? Mostrar errores de validación o mensajes de éxito después de submit.
'use client';import { useFormState } from 'react-dom';
async function createUser(prevState, formData) {'use server';const name = formData.get('name');
if (!name) { return { error: 'Nombre requerido' };}
await db.users.create({ data: { name } });return { success: true };}
function Form() {const [state, formAction] = useFormState(createUser, {});
return ( <form action={formAction}> <input name="name" /> {state.error && <p>{state.error}</p>} <button>Crear</button> </form>);}74. ¿Qué es useOptimistic?
Section titled “74. ¿Qué es useOptimistic?”¿Qué es? Hook para actualizaciones optimistas: mostrar el resultado esperado ANTES de que el servidor confirme.
¿Para qué sirve? UI instantánea. Si falla, se revierte automáticamente.
'use client';import { useOptimistic } from 'react';
function Messages({ messages }) {const [optimisticMessages, addOptimisticMessage] = useOptimistic( messages, (state, newMessage) => [...state, { ...newMessage, sending: true }]);
async function sendMessage(formData) { const message = formData.get('message'); addOptimisticMessage({ text: message }); await deliverMessage(message);}
return ( <> {optimisticMessages.map(m => ( <div key={m.id} style={{ opacity: m.sending ? 0.5 : 1 }}> {m.text} </div> ))} <form action={sendMessage}> <input name="message" /> </form> </>);}75. ¿Qué es React Compiler (React Forget)?
Section titled “75. ¿Qué es React Compiler (React Forget)?”¿Qué es? Compilador que automáticamente memoriza componentes y valores.
¿Para qué sirve? Elimina la necesidad de useMemo, useCallback y React.memo manuales. Optimización automática.
76. ¿Qué son los Actions en React 19?
Section titled “76. ¿Qué son los Actions en React 19?”¿Qué es? Funciones async que se pasan a startTransition. Manejan pending states automáticamente.
¿Para qué sirve? Simplificar manejo de loading/error en operaciones asíncronas.
// Actions - funciones async que manejan transicionesfunction UpdateName() {const [name, setName] = useState('');const [error, setError] = useState(null);const [isPending, startTransition] = useTransition();
const handleSubmit = () => { startTransition(async () => { const error = await updateName(name); if (error) { setError(error); return; } redirect('/profile'); });};}77. ¿Qué es Document Metadata en React 19?
Section titled “77. ¿Qué es Document Metadata en React 19?”¿Qué es? Capacidad de definir <title>, <meta>, <link> directamente en componentes.
¿Para qué sirve? SEO dinámico sin librerías externas. React los mueve automáticamente al <head>.
// Metadata directamente en componentesfunction BlogPost({ post }) {return ( <article> <title>{post.title}</title> <meta name="description" content={post.excerpt} /> <link rel="canonical" href={post.url} />
<h1>{post.title}</h1> <p>{post.content}</p> </article>);}78. ¿Qué es Asset Loading en React 19?
Section titled “78. ¿Qué es Asset Loading en React 19?”¿Qué es? APIs para precargar recursos (DNS, conexiones, fonts, scripts).
¿Para qué sirve? Mejorar performance cargando recursos antes de necesitarlos.
// Precargar recursosimport { prefetchDNS, preconnect, preload, preinit } from 'react-dom';
function Component() {prefetchDNS('https://api.example.com');preconnect('https://api.example.com');preload('/fonts/font.woff2', { as: 'font' });preinit('/scripts/analytics.js', { as: 'script' });
return <div>...</div>;}79. ¿Qué es ref como prop en React 19?
Section titled “79. ¿Qué es ref como prop en React 19?”¿Qué es? En React 19, ref es una prop normal. Ya no necesitas forwardRef.
Beneficio: Código más simple y menos boilerplate.
// React 19 - ref como prop normal (sin forwardRef)function Input({ ref, ...props }) {return <input ref={ref} {...props} />;}
// Usofunction Form() {const inputRef = useRef(null);return <Input ref={inputRef} />;}80. ¿Qué es el Context como provider en React 19?
Section titled “80. ¿Qué es el Context como provider en React 19?”¿Qué es? En React 19, el Context se usa directamente como provider sin .Provider.
Antes: <ThemeContext.Provider>. Ahora: <ThemeContext>.
// React 19 - Context directamente como providerconst ThemeContext = createContext('light');
function App() {return ( <ThemeContext value="dark"> <Page /> </ThemeContext>);}
// Antes (React 18)<ThemeContext.Provider value="dark"><Page /></ThemeContext.Provider>Frameworks y Herramientas (81-90)
Section titled “Frameworks y Herramientas (81-90)”81. ¿Qué es Next.js?
Section titled “81. ¿Qué es Next.js?”¿Qué es? Framework full-stack de React creado por Vercel. El más popular para producción.
Incluye:
- Server-Side Rendering (SSR)
- Static Site Generation (SSG)
- API Routes
- File-based routing
- Server Components
82. ¿Cuál es la diferencia entre SSR, SSG e ISR?
Section titled “82. ¿Cuál es la diferencia entre SSR, SSG e ISR?”SSR (Server-Side Rendering): HTML generado en cada request. SSG (Static Site Generation): HTML generado en build time. ISR (Incremental Static Regeneration): SSG + revalidación periódica.
| Método | Cuándo genera | Uso |
|---|---|---|
| SSR | Cada request | Datos dinámicos |
| SSG | Build time | Contenido estático |
| ISR | Build + revalidación | Estático con actualizaciones |
83. ¿Qué es Remix?
Section titled “83. ¿Qué es Remix?”¿Qué es? Framework de React enfocado en web standards y progressive enhancement.
Características:
- Web standards (forms, fetch)
- Progressive enhancement
- Nested routing
- Data loading/mutations
84. ¿Qué es Vite?
Section titled “84. ¿Qué es Vite?”¿Qué es? Build tool moderno que reemplaza a Create React App. Creado por Evan You (Vue).
Ventajas:
- Dev server ultra rápido (ESM nativo)
- HMR instantáneo
- Build optimizado con Rollup
- Soporte TypeScript nativo
85. ¿Qué es Storybook?
Section titled “85. ¿Qué es Storybook?”¿Qué es? Herramienta para desarrollar y documentar componentes UI en aislamiento.
¿Para qué sirve? Crear catálogo de componentes, testing visual, documentación interactiva.
export default {title: 'Components/Button',component: Button};
export const Primary = {args: { variant: 'primary', children: 'Click me'}};
export const Secondary = {args: { variant: 'secondary', children: 'Click me'}};86. ¿Qué es Playwright/Cypress para testing E2E?
Section titled “86. ¿Qué es Playwright/Cypress para testing E2E?”¿Qué es? Herramientas para testing end-to-end (simular usuario real en browser).
Playwright: Más rápido, multi-browser. Cypress: Más fácil de usar, mejor DX.
// Playwrightimport { test, expect } from '@playwright/test';
test('login flow', async ({ page }) => {await page.goto('/login');await page.fill('[name="email"]', 'test@test.com');await page.fill('[name="password"]', 'password');await page.click('button[type="submit"]');await expect(page).toHaveURL('/dashboard');});87. ¿Qué es MSW (Mock Service Worker)?
Section titled “87. ¿Qué es MSW (Mock Service Worker)?”¿Qué es? Librería para mockear APIs interceptando requests a nivel de red.
¿Para qué sirve? Testing sin backend real, desarrollo offline, simular errores.
import { rest } from 'msw';import { setupServer } from 'msw/node';
const server = setupServer(rest.get('/api/users', (req, res, ctx) => { return res(ctx.json([{ id: 1, name: 'John' }]));}));
beforeAll(() => server.listen());afterEach(() => server.resetHandlers());afterAll(() => server.close());88. ¿Qué es React Native?
Section titled “88. ¿Qué es React Native?”¿Qué es? Framework para construir apps móviles nativas usando React.
¿Cómo funciona? Comparte lógica con web pero usa componentes nativos (View, Text, etc. en vez de div, p).
89. ¿Qué es Expo?
Section titled “89. ¿Qué es Expo?”¿Qué es? Plataforma que simplifica React Native. Recomendada para empezar.
Incluye:
- Sin configuración nativa
- OTA updates
- SDK con APIs comunes
- Expo Go para testing
90. ¿Qué es Framer Motion?
Section titled “90. ¿Qué es Framer Motion?”¿Qué es? Librería de animaciones declarativas para React.
¿Para qué sirve? Animaciones complejas con API simple: entrada, salida, gestos, layout animations.
import { motion } from 'framer-motion';
function Component() {return ( <motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0 }} transition={{ duration: 0.3 }} > Contenido animado </motion.div>);}Preguntas de Arquitectura (91-100)
Section titled “Preguntas de Arquitectura (91-100)”91. ¿Cómo estructurar un proyecto React grande?
Section titled “91. ¿Cómo estructurar un proyecto React grande?”Principio: Agrupar por feature/dominio, no por tipo de archivo.
Estructura recomendada:
src/├── components/ # Componentes reutilizables│ ├── ui/ # Componentes UI básicos│ └── forms/ # Componentes de formulario├── features/ # Features por dominio│ ├── auth/│ │ ├── components/│ │ ├── hooks/│ │ ├── api/│ │ └── index.js│ └── posts/├── hooks/ # Hooks globales├── lib/ # Utilidades├── services/ # API clients├── stores/ # Estado global└── pages/ # Páginas/rutas92. ¿Qué es Feature-Sliced Design?
Section titled “92. ¿Qué es Feature-Sliced Design?”¿Qué es? Arquitectura que organiza código por features y capas con reglas estrictas de dependencias.
Capas (de mayor a menor):
- app/ - Configuración global
- pages/ - Composición de features
- widgets/ - Bloques de UI complejos
- features/ - Funcionalidades de negocio
- entities/ - Entidades de dominio
- shared/ - Código reutilizable
93. ¿Cómo manejar autenticación?
Section titled “93. ¿Cómo manejar autenticación?”Patrón común: Context + Provider que maneja estado de usuario, login, logout, y verificación de sesión.
// Context de autenticaciónconst AuthContext = createContext(null);
function AuthProvider({ children }) {const [user, setUser] = useState(null);const [loading, setLoading] = useState(true);
useEffect(() => { // Verificar sesión al cargar checkAuth().then(setUser).finally(() => setLoading(false));}, []);
const login = async (credentials) => { const user = await api.login(credentials); setUser(user);};
const logout = async () => { await api.logout(); setUser(null);};
return ( <AuthContext.Provider value={{ user, login, logout, loading }}> {children} </AuthContext.Provider>);}94. ¿Cómo implementar internacionalización (i18n)?
Section titled “94. ¿Cómo implementar internacionalización (i18n)?”¿Qué es? Soporte para múltiples idiomas en la aplicación.
Librería popular: react-i18next - archivos JSON con traducciones + hook useTranslation.
// Con react-i18nextimport { useTranslation } from 'react-i18next';
function Welcome() {const { t, i18n } = useTranslation();
return ( <div> <h1>{t('welcome.title')}</h1> <button onClick={() => i18n.changeLanguage('es')}> Español </button> </div>);}
// translations/es.json{"welcome": { "title": "Bienvenido"}}95. ¿Cómo implementar temas (dark/light mode)?
Section titled “95. ¿Cómo implementar temas (dark/light mode)?”Patrón: Context + CSS variables. Guardar preferencia en localStorage.
const ThemeContext = createContext();
function ThemeProvider({ children }) {const [theme, setTheme] = useState(() => localStorage.getItem('theme') || 'light');
useEffect(() => { document.documentElement.setAttribute('data-theme', theme); localStorage.setItem('theme', theme);}, [theme]);
const toggle = () => setTheme(t => t === 'light' ? 'dark' : 'light');
return ( <ThemeContext.Provider value={{ theme, toggle }}> {children} </ThemeContext.Provider>);}96. ¿Cómo manejar formularios complejos?
Section titled “96. ¿Cómo manejar formularios complejos?”Librerías recomendadas: React Hook Form (performance) + Zod (validación con TypeScript).
// Con React Hook Formimport { useForm } from 'react-hook-form';import { zodResolver } from '@hookform/resolvers/zod';import { z } from 'zod';
const schema = z.object({email: z.string().email(),password: z.string().min(8)});
function LoginForm() {const { register, handleSubmit, formState: { errors } } = useForm({ resolver: zodResolver(schema)});
const onSubmit = (data) => console.log(data);
return ( <form onSubmit={handleSubmit(onSubmit)}> <input {...register('email')} /> {errors.email && <span>{errors.email.message}</span>}
<input type="password" {...register('password')} /> {errors.password && <span>{errors.password.message}</span>}
<button type="submit">Login</button> </form>);}97. ¿Cómo implementar infinite scroll?
Section titled “97. ¿Cómo implementar infinite scroll?”¿Qué es? Cargar más contenido automáticamente cuando el usuario llega al final de la lista.
¿Cómo? Usar IntersectionObserver para detectar cuando el último elemento es visible.
function InfiniteList() {const [items, setItems] = useState([]);const [page, setPage] = useState(1);const [hasMore, setHasMore] = useState(true);const observerRef = useRef();const lastItemRef = useRef();
useEffect(() => { observerRef.current = new IntersectionObserver(entries => { if (entries[0].isIntersecting && hasMore) { setPage(p => p + 1); } });
if (lastItemRef.current) { observerRef.current.observe(lastItemRef.current); }
return () => observerRef.current?.disconnect();}, [hasMore, items]);
useEffect(() => { fetchItems(page).then(newItems => { setItems(prev => [...prev, ...newItems]); setHasMore(newItems.length > 0); });}, [page]);
return ( <ul> {items.map((item, i) => ( <li key={item.id} ref={i === items.length - 1 ? lastItemRef : null}> {item.name} </li> ))} </ul>);}98. ¿Cómo implementar WebSockets en React?
Section titled “98. ¿Cómo implementar WebSockets en React?”¿Qué es? Conexión bidireccional en tiempo real entre cliente y servidor.
¿Para qué sirve? Chat, notificaciones en vivo, actualizaciones en tiempo real.
function useWebSocket(url) {const [messages, setMessages] = useState([]);const [isConnected, setIsConnected] = useState(false);const wsRef = useRef(null);
useEffect(() => { wsRef.current = new WebSocket(url);
wsRef.current.onopen = () => setIsConnected(true); wsRef.current.onclose = () => setIsConnected(false); wsRef.current.onmessage = (e) => { setMessages(prev => [...prev, JSON.parse(e.data)]); };
return () => wsRef.current?.close();}, [url]);
const send = useCallback((data) => { wsRef.current?.send(JSON.stringify(data));}, []);
return { messages, isConnected, send };}99. ¿Cómo manejar errores globalmente?
Section titled “99. ¿Cómo manejar errores globalmente?”Estrategia: Error Boundary para errores de render + event listener para errores async.
// Error Boundary globalclass GlobalErrorBoundary extends React.Component {state = { hasError: false, error: null };
static getDerivedStateFromError(error) { return { hasError: true, error };}
componentDidCatch(error, info) { // Enviar a servicio de monitoreo errorService.log(error, info);}
render() { if (this.state.hasError) { return <ErrorPage error={this.state.error} />; } return this.props.children;}}
// Para errores asyncwindow.addEventListener('unhandledrejection', (event) => {errorService.log(event.reason);});100. ¿Cuáles son las mejores prácticas de React?
Section titled “100. ¿Cuáles son las mejores prácticas de React?”Resumen de buenas prácticas:
- Componentes pequeños y enfocados
- Composición sobre herencia
- Estado lo más local posible
- Evitar prop drilling con Context/estado global
- Usar TypeScript
- Testing desde el principio
- Memoización solo cuando sea necesario
- Separar lógica de UI (custom hooks)
- Nombrar componentes descriptivamente
- Documentar componentes complejos