Saltar al contenido principal

v0.13: NextJS App Router, Expo, React 19, Redux

· 9 min de lectura
Nathaniel Tucker
Creator of Reactive Data Client

Plataformas:

Pruebas:

Paquetes movidos dentro de @data-client/react:

  • Redux
  • Hooks

Otras mejoras

Cambios incompatibles:

nota

La versión 0.12 se omitió debido a un percance en la publicación.

Plataformas​

NextJS App Router​

NextJS 12 incluye una nueva forma de enrutamiento en el directorio '/app'. Esto permite más mejoras de rendimiento, así como enrutamiento dinámico y anidado. Esto convierte a NextJS en una plataforma viable para construir aplicaciones dinámicas ricas, en lugar de solo sitios web estáticos.

Mientras que otros métodos de obtención de datos requieren una lenta obtención del lado del cliente, Reactive Data Client ofrece lo mejor de las SPA y de las MPA. #3074, #3093

Como las MPA, el SSR con Data Client significa la carga inicial de página más rápida posible. Como las SPA, Data Client ofrece una navegación, unas mutaciones del lado del cliente y unas mutaciones impulsadas desde el servidor (como websockets) más rápidas que las MPA.

Además, Data Client con SSR sigue ofreciendo las ventajas de rendimiento frente a otras bibliotecas de obtención de datos del lado del cliente.

Rendimiento vs obtención en el cliente
Bar lengths use a log scale
LCP3xClient fetch 1200 ms → Data Client 400 ms
Mutation603xClient fetch 1810 ms → Data Client 3 ms
List to detail navigation6.7xClient fetch 310 ms → Data Client 46 ms

Data Client realiza SSR en streaming del HTML, agilizando la experiencia de carga inicial de la aplicación. De forma única, Data Client queda entonces interactivo de inmediato con 0 obtenciones de datos del lado del cliente. Esto se logra inicializando el Store del cliente con datos normalizados durante la fase de SSR.

Uso​

Renderiza DataProvider desde el punto de entrada /nextjs en tu layout raíz.

app/layout.tsx
import { DataProvider } from '@data-client/react/nextjs';
import { AsyncBoundary } from '@data-client/react';

export default function RootLayout({ children }) {
return (
<html>
<body>
<DataProvider>
<header>Title</header>
<AsyncBoundary>{children}</AsyncBoundary>
<footer></footer>
</DataProvider>
</body>
</html>
);
}

Demo de mutaciones​

Explora el ejemplo nextjs

Más demos

Demo de datos en vivo​

Otros SSR​

Se agrega el punto de entrada /ssr, eliminando por completo la necesidad del paquete @data-client/ssr d1b9e96

Before
import {
createPersistedStore,
createServerDataComponent,
} from '@data-client/ssr';
After
import {
createPersistedStore,
createServerDataComponent,
} from '@data-client/react/ssr';

Esto hace posible integrar fácilmente Data Client en cualquier framework de SSR. Agradecemos las contribuciones para la integración con cualquier framework de código abierto.

Expo​

Hemos comenzado a trabajar en demos de Expo/ExpoGo y, gracias a ello, encontramos y corregimos algunos problemas de compatibilidad con estas integraciones. Por favor, reporta cualquier problema que se nos haya podido escapar.

React 19​

Ahora admitimos React 19. #3071

Esto requirió abandonar el soporte para versiones anteriores a 16.14, ya que debemos usar el runtime de jsx exportado por el propio React. Esto tiene el beneficio adicional de reducir el tamaño del bundle.

Redux​

Se agrega @data-client/react/redux #3099. Esto elimina la necesidad del paquete separado @data-client/redux.

Before
import {
ExternalDataProvider,
PromiseifyMiddleware,
applyManager,
initialState,
createReducer,
prepareStore,
} from '@data-client/redux';
After
import {
ExternalDataProvider,
PromiseifyMiddleware,
applyManager,
initialState,
createReducer,
prepareStore,
} from '@data-client/react/redux';

Se agrega el argumento middlewares a prepareStore() #3099

const { store, selector, controller } = prepareStore(
initialState,
managers,
Controller,
otherReducers,
extraMiddlewares,
);

controller.set()​

controller.set() actualiza cualquier Schema Queryable. #3105, #3129

ctrl.set(
Todo,
{ id: '5' },
{ id: '5', title: 'tell me friends how great Data Client is' },
);

Se pueden usar funciones como valor cuando se trabaja con datos derivados. Esto evita condiciones de carrera.

const id = '2';
ctrl.set(Article, { id }, article => ({ id, votes: article.votes + 1 }));
nota

La respuesta debe incluir valores suficientes para calcular Entity.pk()

Esto hace más directo manipular el store con Managers. Por ejemplo, podemos establecer directamente nuestra entidad Ticker al recibir mensajes de websocket:

Explora el ejemplo coin-app

Más demos

Mejoras de tipos​

Cambios en REST​

Cadenas de path​

Se admiten + y * y {} en RestEndpoint.path. a6b4f4a

const getThing = new RestEndpoint({
path: '/:attr1?{-:attr2}?{-:attr3}?',
});

getThing({ attr1: 'hi' });
getThing({ attr2: 'hi' });
getThing({ attr3: 'hi' });
getThing({ attr1: 'hi', attr3: 'ho' });
getThing({ attr2: 'hi', attr3: 'ho' });

ctrl.fetch() y Unions​

Los valores de Unions en el valor de retorno de ctrl.fetch() ahora son una instancia de su clase Entity. #3063

import { getFeed } from './Feed';

function useFeedHandler() {
  const ctrl = useController();

  const handleSomething = async () => {
    const feed = await ctrl.fetch(getFeed);
    return feed.map(item => {
      if (item.type == 'link') {
        // we can use class defined getter
        return item.anchor;
      }
    });
  }
  return handleSomething;
}

Guía de migración​

Esta actualización requiere actualizar todas las versiones de los paquetes simultáneamente.

npm install --save @data-client/react@^0.13.0 @data-client/rest@^0.13.0 @data-client/test@^0.13.0 @data-client/img@^0.13.0

actionTypes.SET_TYPE -> actionTypes.SET_RESPONSE_TYPE​

Si escribiste un Manager personalizado que manejaba actionTypes.SET_TYPE, tendrás que renombrarlo a actionTypes.SET_RESPONSE_TYPE.

Before
import type { Manager, Middleware } from '@data-client/react';
import { actionTypes } from '@data-client/react';

export default class LoggingManager implements Manager {
middleware: Middleware = controller => next => async action => {
switch (action.type) {
case actionTypes.SET_TYPE:
console.info(
`${action.endpoint.name} ${JSON.stringify(action.response)}`,
);
return next(action);
// actions must be explicitly passed to next middleware
default:
return next(action);
}
};

cleanup() {}
}
After
import type { Manager, Middleware } from '@data-client/react';
import { actionTypes } from '@data-client/react';

export default class LoggingManager implements Manager {
middleware: Middleware = controller => next => async action => {
switch (action.type) {
case actionTypes.SET_RESPONSE_TYPE:
console.info(
`${action.endpoint.name} ${JSON.stringify(action.response)}`,
);
return next(action);
// actions must be explicitly passed to next middleware
default:
return next(action);
}
};

cleanup() {}
}

SetAction -> SetResponseAction​

React 16.14+​

Cambia la versión mínima de React de 16.8.4 -> 16.14. No se necesitan cambios en el código.

npm install --save react@16.14 react-dom@16.14

CacheProvider -> DataProvider​

Pásate a DataProvider para mantener la compatibilidad con versiones futuras. También se exporta como CacheProvider, así que no es un cambio incompatible. #3095

Before
import { CacheProvider } from '@data-client/react';
import ReactDOM from 'react-dom';

ReactDOM.createRoot(document.body)
.render(
<CacheProvider>
<App />
</CacheProvider>,
);
Before
import { DataProvider } from '@data-client/react';
import ReactDOM from 'react-dom';

ReactDOM.createRoot(document.body)
.render(
<DataProvider>
<App />
</DataProvider>,
);

Soporte para la actualización​

Como siempre, si tienes algún problema o pregunta, no dudes en unirte a nuestro Chat o reportar un error