We want to hear from you!Take our 2021 Community Survey!
¡Prueba un avance de la nueva documentación de React!👉 beta.es.reactjs.org

Referencia de la API de los Hooks

Los Hooks son una nueva incorporación en React 16.8. Te permiten usar estado y otras características de React sin escribir una clase.

Esta página describe las API para los Hooks incorporados en React.

Si los Hooks son nuevos para ti, es posible que desees revisar primero la descripción general. También puedes encontrar información útil en la sección de preguntas frecuentes.

Hooks básicos

useState

const [state, setState] = useState(initialState);

Devuelve un valor con estado y una función para actualizarlo.

Durante el renderizado inicial, el estado devuelto (state) es el mismo que el valor pasado como primer argumento (initialState).

La función setState se usa para actualizar el estado. Acepta un nuevo valor de estado y sitúa en la cola una nueva renderización del componente.

setState(newState);

En las renderizaciones siguientes, el primer valor devuelto por useState será siempre el estado más reciente después de aplicar las actualizaciones.

Nota

React garantiza que la identidad de la función setState es estable y no cambiará en subsecuentes renderizados. Es por eso que es seguro omitirla de la lista de dependencias de useEffect o useCallback.

Actualizaciones funcionales

Si el nuevo estado se calcula utilizando el estado anterior, puede pasar una función a setState. La función recibirá el valor anterior y devolverá un valor actualizado. Aquí hay un ejemplo de un componente contador que usa ambas formas de setState:

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
    </>
  );
}

Los botones ”+” y ”-” usan la forma funcional, porque el valor actualizado se basa en el valor anterior. Pero el botón “Reset” usa la forma normal, porque siempre vuelve a establecer la cuenta al valor inicial.

Si tu función de actualización retorna el mismo valor que el valor del estado actual, el renderizado subsecuente será omitido completamente.

Nota

A diferencia del método setState que se encuentra en los componentes de la clase,useState no combina automáticamente los objetos. Puede replicar este comportamiento combinando la función de actualizador de función con la sintaxis de propagación de objetos:

const [state, setState] = useState({});
setState(prevState => {
  // Object.assign también funcionaría
  return {...prevState, ...updatedValues};
});

Otra opción es useReducer, que es más adecuada para administrar objetos de estado que contienen múltiples subvalores.

Inicialización gradual

El argumento initialState es el estado utilizado durante el render inicial. En renderizados posteriores, se ignora. Si el estado inicial es el resultado de un cálculo costoso, puede proporcionar una función en su lugar, que se ejecutará solo en el render inicial:

const [state, setState] = useState(() => {
  const initialState = someExpensiveComputation(props);
  return initialState;
});

Evitar una actualización del estado

Si se actualiza un Hook de estado con el mismo valor que el estado actual, React evitará renderizar los hijos y disparar los efectos. (React utiliza el algoritmo de comparación Object.is).

Recuerda que React puede necesitar renderizar de nuevo ese componente en específico antes de evitarlo. Esto no debería ser un problema ya que React no irá innecesariamente “más profundo” en el árbol. Si estás realizando cálculos costosos mientras renderizas, puedes optimizarlos con useMemo.

Batching of state updates

React may group several state updates into a single re-render to improve performance. Normally, this improves performance and shouldn’t affect your application’s behavior.

Before React 18, only updates inside React event handlers were batched. Starting with React 18, batching is enabled for all updates by default. Note that React makes sure that updates from several different user-initiated events — for example, clicking a button twice — are always processed separately and do not get batched. This prevents logical mistakes.

In the rare case that you need to force the DOM update to be applied synchronously, you may wrap it in flushSync. However, this can hurt performance so do this only where needed.

useEffect

useEffect(didUpdate);

Acepta una función que contiene código imperativo, posiblemente código efectivo.

Las mutaciones, suscripciones, temporizadores, registro y otros efectos secundarios no están permitidos dentro del cuerpo principal de un componente de función (denominado como render phase de React). Si lo hace, dará lugar a errores confusos e inconsistencias en la interfaz de usuario.

En su lugar, use useEffect. La función pasada a useEffect se ejecutará después de que el renderizado es confirmado en la pantalla. Piense en los efectos como una escotilla de escape de React del mundo puramente funcional al mundo imperativo.

Por defecto, los efectos se ejecutan después de cada renderizado completado, pero puede elegir ejecutarlo solo cuando ciertos valores han cambiado.

Limpiando un efecto

A menudo, los efectos crean recursos que deben limpiarse antes de que el componente salga de la pantalla, como una suscripción o un ID de temporizador. Para hacer esto, la función pasada a useEffect puede devolver una función de limpieza. Por ejemplo, para crear una suscripción:

useEffect(() => {
  const subscription = props.source.subscribe();
  return () => {
    // Limpiar la suscripción
    subscription.unsubscribe();
  };
});

La función de limpieza se ejecuta antes de que el componente se elimine de la interfaz de usuario para evitar pérdidas de memoria. Además, si un componente se procesa varias veces (como suele hacer), el efecto anterior se limpia antes de ejecutar el siguiente efecto. En nuestro ejemplo, esto significa que se crea una nueva suscripción en cada actualización. Para evitar disparar un efecto en cada actualización, consulte la siguiente sección.

Tiempo de los efectos

A diferencia de componentDidMount ycomponentDidUpdate, la función enviada a useEffect se inicia después de la disposición y pintada de la página, durante un evento diferido. Esto lo hace adecuado para los muchos efectos secundarios comunes, como la configuración de suscripciones y los controladores de eventos, porque la mayoría de los tipos de trabajo no deben impedir que el navegador actualice la pantalla.

Sin embargo, no todos los efectos pueden ser diferidos. Por ejemplo, una mutación de DOM que es visible para el usuario debe ejecutarse de manera sincrónica antes del siguiente render para que el usuario no perciba una inconsistencia visual. (La distinción es conceptualmente similar a la de los listeners de eventos pasivos y de los activos). Para estos tipos de efectos, React proporciona un Hook adicional llamado useLayoutEffect. Tiene la misma firma que useEffect y solo difiere de este último en cuándo se ejecuta.

Adicionalmente, a partir de React 18, la función que se pasa a useEffect se ejecutará sincrónicamente antes de las etapas de layout y pintura cuando es el resulta de una entrada discreta del usuario como un clic, o cuando el resultado de una actualización envuelta en flushSync. Este comportamiento permite que el resultado del efecto sea observado por un sistema de eventos o por quien llama a flushSync.

Nota

Esto solo afecta el tiempo de llamada de la función pasada a useEffect - las actualizaciones que se programan dentro de estos efectos aún se difieren. Esto es diferente a useLayoutEffect, que invoca la función y procesa las actualizaciones dentro de ella inmediatamente.

Aún en los casos en que useEffect se aplaza hasta después de que el navegador haya pintado, se garantiza que se activará antes de cualquier nuevo render. React siempre eliminará los efectos de un render anterior antes de comenzar una nueva actualización.

Disparar un efecto condicionalmente.

El comportamiento predeterminado para los efectos es ejecutar el efecto después de cada renderizado que se completa. De esa manera, siempre se recrea un efecto si cambia una de sus dependencias.

Sin embargo, esto puede ser excesivo en algunos casos, como el ejemplo de suscripción de la sección anterior. No necesitamos crear una nueva suscripción en cada actualización, solo si las propiedades de source han cambiado.

Para implementar esto, pase un segundo argumento a useEffect que es el conjunto de valores de los que depende el efecto. Nuestro ejemplo actualizado se verá así:

useEffect(
  () => {
    const subscription = props.source.subscribe();
    return () => {
      subscription.unsubscribe();
    };
  },
  [props.source],
);

Ahora la suscripción solo se volverá a crear cuando cambie props.source.

Nota

Si usas esta optimización, asegúrate de que incluyes todos los valores del ámbito del componente (como props y estado) que cambien a lo largo del tiempo y que sean usados por el efecto. De otra forma, tu código referenciará valores obsoletos de renderizados anteriores. Aprende más cómo tratar con funciones y qué hacer cuando el array cambia con mucha frecuencia.

Si quieres ejecutar un efecto y sanearlo solamente una vez (al montar y desmontar), puedes pasar un array vacío ([]) como segundo argumento. Esto le indica a React que el efecto no depende de ningún valor proviniente de las props o el estado, de modo que no necesita volver a ejecutarse. Esto no se gestiona como un caso especial, obedece directamente al modo en el que siempre funcionan los arrays.

Si pasas un array vacío ([]), las props y el estado dentro del efecto siempre tendrán sus valores iniciales. Si bien pasar [] como segundo argumento se acerca al conocido modelo mental de componentDidMount y componentWillUnmount, a menudo hay mejores soluciones para evitar volver a ejecutar los efectos con demasiada frecuencia. Además, no olvides que React pospone la ejecución de useEffect hasta que el navegador finaliza el trazado, de modo que hacer algún trabajo extra no es tan problemático.

Recomendamos usar la regla exhaustive-deps que forma parte de nuestro paquete eslint-plugin-react-hooks. Esta regla advierte cuando las dependencias se especifican incorrectamente y sugiere una solución.

El arreglo de entradas no se pasa como argumentos a la función de efecto. Sin embargo, conceptualmente, eso es lo que representan: cada valor al que se hace referencia dentro de la función de efecto también debería aparecer en el arreglo de entradas. En el futuro, un compilador lo suficientemente avanzado podría crear este arreglo automáticamente.

useContext

const value = useContext(MyContext);

Acepta un objeto de contexto (el valor devuelto de React.createContext) y devuelve el valor de contexto actual. El valor actual del contexto es determinado por la propiedad value del <MyContext.Provider> ascendentemente más cercano en el árbol al componente que hace la llamada.

Cuando el <MyContext.Provider> ascendentemente más cercano en el árbol se actualiza, el Hook activa una renderización con el value más reciente del contexto pasado a ese proveedor MyContext. Incluso sí un ancestro utiliza React.memo o shouldComponentUpdate, una nueva renderización aún pasará empezando con el componente en si mismo usando useContext.

No olvides que el argumento enviado a useContext debe ser el objeto del contexto en sí mismo:

  • Correcto: useContext(MyContext)
  • Incorrecto: useContext(MyContext.Consumer)
  • Incorrecto: useContext(MyContext.Provider)

Un componente que llama a useContext siempre se volverá a renderizar cuando el valor del contexto cambie. Si volver a renderizar el componente es costoso, puedes optimizar esto usando memorización.

Consejo

Si estás familiarizado con el API de contexto antes de Hooks, useContext(MyContext) es el equivalente a static contextType = MyContext en una clase, o a <MyContext.Consumer>.

useContext(MyContext) solo te permite leer el contexto y suscribirte a sus cambios. Aún necesitas un <MyContext.Provider> arriba en el árbol para proveer el valor para este contexto.

Poniendo todo junto con Context.Provider

const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee"
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222"
  }
};

const ThemeContext = React.createContext(themes.light);

function App() {
  return (
    <ThemeContext.Provider value={themes.dark}>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  const theme = useContext(ThemeContext);  return (    <button style={{ background: theme.background, color: theme.foreground }}>      I am styled by theme context!    </button>  );
}

Este ejemplo está modificado para Hooks a partir del ejemplo anterior en de la guía avanzada de Context, donde puedes encontrar más información sobre cuando y cómo usar Context.

Hooks adicionales

Los siguientes Hooks son variantes de los básicos de la sección anterior o solo son necesarios para casos extremos específicos. No te estreses por aprenderlos por adelantado.

useReducer

const [state, dispatch] = useReducer(reducer, initialArg, init);

Una alternativa a useState. Acepta un reducer de tipo (state, action) => newState y devuelve el estado actual emparejado con un método dispatch. (Si está familiarizado con Redux, ya sabe cómo funciona).

useReducer a menudo es preferible a useState cuando se tiene una lógica compleja que involucra múltiples subvalores o cuando el próximo estado depende del anterior. useReducer además te permite optimizar el rendimiento para componentes que activan actualizaciones profundas, porque puedes pasar hacia abajo dispatch en lugar de callbacks.

Aquí está el ejemplo del contador de la sección [useState], reescrito para usar un reductor:

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: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

Nota

React garantiza que la identidad de la función dispatch es estable y no cambiará en subsecuentes renderizados. Es por eso que es seguro omitirla de la lista de dependencias de useEffect o useCallback.

Especificar el estado inicial

Hay dos formas diferentes de inicializar el estado de useReducer. Puedes elegir uno u otro dependiendo de tu caso. La forma más simple para pasar el estado inicial es como un segundo argumento:

  const [state, dispatch] = useReducer(
    reducer,
    {count: initialCount}  );

Nota

React no utiliza la convención del argumento state = initialState popularizada por Redux. El valor inicial a veces necesita tener una dependencia en las props y por lo tanto tanto se especifica en la llamada al Hook. Si te parece muy importante, puedes llamar a useReducer(reducer, undefined, reducer) para emular el comportamiento de Redux, pero no se recomienda

Inicialización diferida

También puedes crear el estado inicial de manera diferida. Para hacerlo, le puedes pasar una función init como tercer argumento. El estado inicial será establecido como init(initialArg).

Esto te permite extraer la lógica para calcular el estado inicial fuera del reductor. También es útil para reiniciar el estado luego en respuesta a una acción:

function init(initialCount) {  return {count: initialCount};}
function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    case 'reset':      return init(action.payload);    default:
      throw new Error();
  }
}

function Counter({initialCount}) {
  const [state, dispatch] = useReducer(reducer, initialCount, init);  return (
    <>
      Count: {state.count}
      <button
        onClick={() => dispatch({type: 'reset', payload: initialCount})}>        Reset
      </button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

Evitar un dispatch

Si devuelves el mismo valor del estado actual desde un Hook reductor, React evitará renderizar los hijos y disparar efectos. (React utiliza el algoritmo de comparación Object.is).

Ten en cuenta que React podría aún necesitar renderizar nuevamente ese componente específico antes de evitar el renderizado. Esto no debería ser una preocupación ya que React no va “más adentro” del árbol de forma innecesaria. Si estás haciendo cálculos muy costosos mientras renderizas, puedes optimizarlos con useMemo.

useCallback

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

Devuelve un callback memorizado.

Pasa un callback en línea y un arreglo de dependencias. useCallback devolverá una versión memorizada del callback que solo cambia si una de las dependencias ha cambiado. Esto es útil cuando se transfieren callbacks a componentes hijos optimizados que dependen de la igualdad de referencia para evitar renders innecesarias (por ejemplo, shouldComponentUpdate).

useCallback(fn, deps) es igual a useMemo(() => fn, deps).

Nota

El arreglo de dependencias no se pasa como argumentos al callback. Sin embargo, conceptualmente, eso es lo que representan: cada valor al que se hace referencia dentro del callback también debe aparecer en el arreglo de dependencias. En el futuro, un compilador lo suficientemente avanzado podría crear este arreglo automáticamente.

Recomendamos usar la regla exhaustive-deps que forma parte de nuestro paquete eslint-plugin-react-hooks. Esta regla advierte cuando las dependencias se especifican incorrectamente y sugiere una solución.

useMemo

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

Devuelve un valor memorizado.

Pasa una función de “crear” y un arreglo de dependencias. useMemo solo volverá a calcular el valor memorizado cuando una de las dependencias haya cambiado. Esta optimización ayuda a evitar cálculos costosos en cada render.

Recuerde que la función pasada a useMemo se ejecuta durante el renderizado. No hagas nada allí que normalmente no harías al renderizar. Por ejemplo, los efectos secundarios pertenecen a useEffect, no auseMemo.

Si no se proporciona un arreglo, se calculará un nuevo valor en cada renderizado.

Puede confiar en useMemo como una optimización del rendimiento, no como una garantía semántica. En el futuro, React puede elegir “olvidar” algunos valores previamente memorizados y recalcularlos en el próximo renderizado, por ejemplo para liberar memoria para componentes fuera de pantalla. Escribe tu código para que aún funcione sin useMemo - y luego agrégalo para optimizar el rendimiento.

Nota

El arreglo de dependencias no se pasa como argumentos a la función. Sin embargo, conceptualmente, eso es lo que representan: cada valor al que se hace referencia dentro de la función también debe aparecer en el arreglo de dependencias. En el futuro, un compilador lo suficientemente avanzado podría crear este arreglo automáticamente.

Recomendamos usar la regla exhaustive-deps que forma parte de nuestro paquete eslint-plugin-react-hooks. Esta regla advierte cuando las dependencias se especifican incorrectamente y sugiere una solución.

useRef

const refContainer = useRef(initialValue);

useRef devuelve un objeto ref mutable cuya propiedad .current se inicializa con el argumento pasado (initialValue). El objeto devuelto se mantendrá persistente durante la vida completa del componente.

Un caso de uso común es para acceder a un hijo imperativamente:

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` apunta al elemento de entrada de texto montado
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

En esencia, useRef es como una “caja” que puedes mantener en una variable mutable en su propiedad .current.

Puede que estes familiarizado con las referencias principalmente como un medio para acceder al DOM. Si pasas un objeto de referencia a React con <div ref={myRef} />, React configurará su propiedad .current al nodo del DOM correspondiente cuando sea que el nodo cambie.

Sin embargo, useRef() es útil para más que el atributo ref. Es conveniente para mantener cualquier valor mutable que es similiar a como usarías campos de instancia en las clases.

Esto funciona debido a que useRef() crea un objeto JavaScript plano. La única diferencia entre useRef() y crear un objeto {current: ...} por ti mismo es que useRef te dará el mismo objeto de referencia en cada renderizado.

Ten en cuenta que useRef no notifica cuando su contenido cambia. Mutar la propiedad .current no causa otro renderizado. Si quieres correr algún código cuando React agregue o quite una referencia de un nodo del DOM, puede que quieras utilizar en su lugar una referencia mediante callback.

useImperativeHandle

useImperativeHandle(ref, createHandle, [deps])

useImperativeHandle personaliza el valor de instancia que se expone a los componentes padres cuando se usaref. Como siempre, el código imperativo que usa refs debe evitarse en la mayoría de los casos. useImperativeHandle debe usarse con forwardRef:

function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);

En este ejemplo, un componente padre que muestra <FancyInput ref={inputRef} /> podría llamar a inputRef.current.focus().

useLayoutEffect

La firma es idéntica a useEffect, pero se dispara de forma síncrona después de todas las mutaciones de DOM. Use esto para leer el diseño del DOM y volver a renderizar de forma sincrónica. Las actualizaciones programadas dentro de useLayoutEffect se vaciarán sincrónicamente, antes de que el navegador tenga la oportunidad de pintar.

Prefiera el useEffect estándar cuando sea posible para evitar el bloqueo de actualizaciones visuales.

Consejo

Si estas migrando código de un componente de clase, recuerda que useLayoutEffect se activa en la misma fase que componentDidMount y componentDidUpdate. Sin embargo, recomendamos empezar con useEffect primero y solo intentar con useLayoutEffect si lo anterior causa problemas.

Si usas renderizado en el servidor, ten en cuenta que ni useLayoutEffect ni useEffect pueden ejecutarse hasta que no se haya descargado el código JavaScript. Por eso es que React advierte cuando un componente renderizado en el servidor contiene useLayoutEffect. Para corregirlo, puedes o bien mover la lógica a useEffect (si no es necesaria para el primer renderizado), o retrasar el momento de mostrar el componente hasta después de que se haya renderizado el cliente (si el HTML luciera roto, hasta que se ejecute useLayoutEffect).

Para excluir del HTML renderizado en el servidor a un componente que necesita efectos de layout, renderízalo condicionalmente con showChild && <Child /> y retrasa mostrarlo con useEffect(() => { setShowChild(true); }, []). De esta manera, la interfaz de usuario no lucirá rota antes de la hidratación.

useDebugValue

useDebugValue(value)

useDebugValue puede usarse para mostrar una etiqueta para Hooks personalizados en React DevTools.

Por ejemplo, considera el Hook personalizado useFriendStatus descrito en “Construyendo sus propios Hooks”:

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  // ...

  // Mostrar una etiqueta en DevTools junto a este Hook  // por ejemplo: "FriendStatus: Online"  useDebugValue(isOnline ? 'Online' : 'Offline');
  return isOnline;
}

Consejo

No recomendamos agregar valores de depuración a cada Hook personalizado. Es más valioso para los Hooks personalizados que forman parte de bibliotecas compartidas.

Aplazar el formato de los valores de depuración

En algunos casos, formatear un valor para mostrar puede ser una operación costosa. También es innecesario a menos que un Hook sea realmente inspeccionado.

Por esta razón, useDebugValue acepta una función de formato como un segundo parámetro opcional. Esta función solo se llama si se inspeccionan los Hooks. Recibe el valor de depuración como parámetro y debe devolver un valor de visualización formateado.

Por ejemplo, un Hook personalizado que devolvió un valor de Date podría evitar llamar a la función toDateString innecesariamente al pasar el siguiente formateador:

useDebugValue(date, date => date.toDateString());

useDeferredValue

const deferredValue = useDeferredValue(value);

useDeferredValue accepts a value and returns a new copy of the value that will defer to more urgent updates. If the current render is the result of an urgent update, like user input, React will return the previous value and then render the new value after the urgent render has completed.

This hook is similar to user-space hooks which use debouncing or throttling to defer updates. The benefits to using useDeferredValue is that React will work on the update as soon as other work finishes (instead of waiting for an arbitrary amount of time), and like startTransition, deferred values can suspend without triggering an unexpected fallback for existing content.

Memoizing deferred children

useDeferredValue only defers the value that you pass to it. If you want to prevent a child component from re-rendering during an urgent update, you must also memoize that component with React.memo or React.useMemo:

function Typeahead() {
  const query = useSearchQuery('');
  const deferredQuery = useDeferredValue(query);

  // Memoizing tells React to only re-render when deferredQuery changes,
  // not when query changes.
  const suggestions = useMemo(() =>
    <SearchSuggestions query={deferredQuery} />,
    [deferredQuery]
  );

  return (
    <>
      <SearchInput query={query} />
      <Suspense fallback="Loading results...">
        {suggestions}
      </Suspense>
    </>
  );
}

Memoizing the children tells React that it only needs to re-render them when deferredQuery changes and not when query changes. This caveat is not unique to useDeferredValue, and it’s the same pattern you would use with similar hooks that use debouncing or throttling.

useTransition

const [isPending, startTransition] = useTransition();

Returns a stateful value for the pending state of the transition, and a function to start it.

startTransition lets you mark updates in the provided callback as transitions:

startTransition(() => {
  setCount(count + 1);
});

isPending indicates when a transition is active to show a pending state:

function App() {
  const [isPending, startTransition] = useTransition();
  const [count, setCount] = useState(0);
  
  function handleClick() {
    startTransition(() => {
      setCount(c => c + 1);
    });
  }

  return (
    <div>
      {isPending && <Spinner />}
      <button onClick={handleClick}>{count}</button>
    </div>
  );
}

Note:

Updates in a transition yield to more urgent updates such as clicks.

Updates in a transition will not show a fallback for re-suspended content. This allows the user to continue interacting with the current content while rendering the update.

useId

const id = useId();

useId is a hook for generating unique IDs that are stable across the server and client, while avoiding hydration mismatches.

Note

useId is not for generating keys in a list. Keys should be generated from your data.

For a basic example, pass the id directly to the elements that need it:

function Checkbox() {
  const id = useId();
  return (
    <>
      <label htmlFor={id}>Do you like React?</label>
      <input id={id} type="checkbox" name="react"/>
    </>
  );
};

For multiple IDs in the same component, append a suffix using the same id:

function NameFields() {
  const id = useId();
  return (
    <div>
      <label htmlFor={id + '-firstName'}>First Name</label>
      <div>
        <input id={id + '-firstName'} type="text" />
      </div>
      <label htmlFor={id + '-lastName'}>Last Name</label>
      <div>
        <input id={id + '-lastName'} type="text" />
      </div>
    </div>
  );
}

Note:

useId generates a string that includes the : token. This helps ensure that the token is unique, but is not supported in CSS selectors or APIs like querySelectorAll.

useId supports an identifierPrefix to prevent collisions in multi-root apps. To configure, see the options for hydrateRoot and ReactDOMServer.

Library Hooks

The following Hooks are provided for library authors to integrate libraries deeply into the React model, and are not typically used in application code.

useSyncExternalStore

const state = useSyncExternalStore(subscribe, getSnapshot[, getServerSnapshot]);

useSyncExternalStore is a hook recommended for reading and subscribing from external data sources in a way that’s compatible with concurrent rendering features like selective hydration and time slicing.

This method returns the value of the store and accepts three arguments:

  • subscribe: function to register a callback that is called whenever the store changes.
  • getSnapshot: function that returns the current value of the store.
  • getServerSnapshot: function that returns the snapshot used during server rendering.

The most basic example simply subscribes to the entire store:

const state = useSyncExternalStore(store.subscribe, store.getSnapshot);

However, you can also subscribe to a specific field:

const selectedField = useSyncExternalStore(
  store.subscribe,
  () => store.getSnapshot().selectedField,
);

When server rendering, you must serialize the store value used on the server, and provide it to useSyncExternalStore. React will use this snapshot during hydration to prevent server mismatches:

const selectedField = useSyncExternalStore(
  store.subscribe,
  () => store.getSnapshot().selectedField,
  () => INITIAL_SERVER_SNAPSHOT.selectedField,
);

Note:

getSnapshot must return a cached value. If getSnapshot is called multiple times in a row, it must return the same exact value unless there was a store update in between.

A shim is provided for supporting multiple React versions published as use-sync-external-store/shim. This shim will prefer useSyncExternalStore when available, and fallback to a user-space implementation when it’s not.

As a convenience, we also provide a version of the API with automatic support for memoizing the result of getSnapshot published as use-sync-external-store/with-selector.

useInsertionEffect

useInsertionEffect(didUpdate);

The signature is identical to useEffect, but it fires synchronously before all DOM mutations. Use this to inject styles into the DOM before reading layout in useLayoutEffect. Since this hook is limited in scope, this hook does not have access to refs and cannot schedule updates.

Note:

useInsertionEffect should be limited to css-in-js library authors. Prefer useEffect or useLayoutEffect instead.

¿Es útil esta página?Edita esta página