v0.13: NextJS App Router, Expo, React 19, Redux
Platforms:
Packages moved inside @data-client/react:
- Redux
- Hooks
Other Improvements
- Added controller.set(Todo, { id }, { id, completed: false })
- RestEndpoint.path supports +, * and {}
- Fixed controller.fetch() return value for Unions
- actionTypes.SET_TYPE -> actionTypes.SET_RESPONSE_TYPE
- SetAction -> SetResponseAction
- Min React version 16.8.4 -> 16.14
Version 0.12 was skipped due to a publishing mishap.
Platforms
NextJS App Router
NextJS 12 includes a new way of routing in the '/app' directory. This allows further performance improvements, as well as dynamic and nested routing. This makes NextJS a viable platform to build rich dynamic applications, rather than just static websites.
While other fetching methods require slow client-side fetching; Reactive Data Client provides the best of both SPA and MPA. #3074, #3093
Like MPAs, SSR with Data Client means the fastest possible initial page load. Like SPAs, Data Client offers faster navigation, client side mutations, and remote-driven mutations (like websockets) than MPAs.
Additionally, Data Client with SSR still provides the performance advantages over other client-side fetching libraries.
Data Client performs streaming SSR of the HTML, streamlining the initial application load experience. Uniquely, Data Client is then immediately interactive with 0 client side fetches. This is achieved by initializing the Client Store with normalized data during the SSR phase.
Usage
Render DataProvider from the /nextjs entrypoint in your root layout.
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>
);
}
Mutations demo
Live data demo
Other SSR
Add /ssr entrypoint - eliminating the need for @data-client/ssr package completely d1b9e96
import {
createPersistedStore,
createServerDataComponent,
} from '@data-client/ssr';
import {
createPersistedStore,
createServerDataComponent,
} from '@data-client/react/ssr';
This makes it possible to easily integrate Data Client into any SSR framework. We welcome contributions for integration with any open source framework.
Expo
We have begun work on Expo/ExpoGo demos, and thus found and fixed some compatibility issues by these integrations. Please report any issues that we may have missed.
React 19
We now support React 19. #3071
This required dropping support for versions less than 16.14, as we must use the jsx runtime exported from React itself. This has the added benefit of reducing the bundle size.
Redux
Add @data-client/react/redux #3099. This removes the need for the separate @data-client/redux package.
import {
ExternalDataProvider,
PromiseifyMiddleware,
applyManager,
initialState,
createReducer,
prepareStore,
} from '@data-client/redux';
import {
ExternalDataProvider,
PromiseifyMiddleware,
applyManager,
initialState,
createReducer,
prepareStore,
} from '@data-client/react/redux';
Add middlewares argument to prepareStore() #3099
const { store, selector, controller } = prepareStore(
initialState,
managers,
Controller,
otherReducers,
extraMiddlewares,
);
controller.set()
controller.set() updates any Queryable Schema. #3105, #3129
ctrl.set(
Todo,
{ id: '5' },
{ id: '5', title: 'tell me friends how great Data Client is' },
);
Functions can be used in the value when derived data is used. This prevents race conditions.
const id = '2';
ctrl.set(Article, { id }, article => ({ id, votes: article.votes + 1 }));
The response must include values sufficient to compute Entity.pk()
This makes it more straightforward to manipulate the store with Managers.
For example we can directly set our Ticker
entity when receiving websocket messages:
Type improvements
-
Improve controller type matching for its methods #3043
-
Improve useFetch() argtype matching similar to useSuspense() #3043
REST changes
path strings
Support + and * and {} in 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() and Unions
Unions values in ctrl.fetch() return value are now an instance of their Entity class. #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; }
Migration guide
This upgrade requires updating all package versions simultaneously.
- NPM
- Yarn
- pnpm
- esm.sh
yarn add @data-client/react@^0.13.0 @data-client/rest@^0.13.0 @data-client/test@^0.13.0 @data-client/img@^0.13.0
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
pnpm add @data-client/react@^0.13.0 @data-client/rest@^0.13.0 @data-client/test@^0.13.0 @data-client/img@^0.13.0
<script type="module">
import * from 'https://esm.sh/@data-client/react@^0.13.0';
import * from 'https://esm.sh/@data-client/rest@^0.13.0';
import * from 'https://esm.sh/@data-client/test@^0.13.0';
import * from 'https://esm.sh/@data-client/img@^0.13.0';
</script>
actionTypes.SET_TYPE -> actionTypes.SET_RESPONSE_TYPE
If you wrote a custom Manager that handled actionTypes.SET_TYPE
, you'll need
to rename it actionTypes.SET_RESPONSE_TYPE.
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() {}
}
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+
Changes the minimum React version from 16.8.4 -> 16.14. There are no code updates needed.
- NPM
- Yarn
- pnpm
- esm.sh
yarn add [email protected] [email protected]
npm install --save [email protected] [email protected]
pnpm add [email protected] [email protected]
<script type="module">
import * from 'https://esm.sh/[email protected]';
import * from 'https://esm.sh/[email protected]';
</script>
CacheProvider -> DataProvider
Move to DataProvider for future version compatibility. It is also
exported as CacheProvider
so this is not a breaking change. #3095
import { CacheProvider } from '@data-client/react';
import ReactDOM from 'react-dom';
ReactDOM.createRoot(document.body)
.render(
<CacheProvider>
<App />
</CacheProvider>,
);
import { DataProvider } from '@data-client/react';
import ReactDOM from 'react-dom';
ReactDOM.createRoot(document.body)
.render(
<DataProvider>
<App />
</DataProvider>,
);
Upgrade support
As usual, if you have any troubles or questions, feel free to join our or file a bug