v0.18: Scalar, Typed File Downloads, Filter-aware Collections
v0.18 focuses on richer data modeling for values that vary by request context, simpler typed downloads, and collection matching that better reflects real API filters.
New Features:
- Scalar schema - Lens-dependent entity fields (e.g. portfolio-specific values) without ever mutating the underlying entity
- RestEndpoint
contentproperty - Typed file downloads, text responses, and streaming with a single property - resource()
nonFilterArgumentKeys- Sort/pagination args don't fragment your Collections
Other Improvements:
- Binary Content-Type auto-detection - Images, PDFs, and other binary responses are handled automatically with no configuration (#3868)
- Collection extender body types match HTTP method semantics - PATCH extenders (
.move,.remove) accept partial bodies; standalone RestEndpoint derives a typed body from the Collection's entity schema (#3910) - Export
CollectionOptionsfrom@data-client/endpointand@data-client/restfor typed Collection construction (#3904)
import { useSuspense, useFetch } from '@data-client/react'; import { getCompanies, getPortfolioColumns } from './api/Company'; import CompanyGrid from './CompanyGrid'; function PortfolioGrid() { const [portfolio, setPortfolio] = React.useState('A'); // Fetches on first render, then re-denormalizes from cache on every // portfolio switch. The Collection's `queryKey()` ignores `portfolio`, // so there is no endpoint refetch on switch. const companies = useSuspense(getCompanies, { portfolio }); // The first render's `useSuspense` already populated `Scalar(portfolio)` // for `firstPortfolio`, so we only fetch columns when the user switches // away. `useFetch` then dedupes later revisits via its endpoint cache. const firstPortfolio = React.useRef(portfolio).current; useFetch( getPortfolioColumns, portfolio === firstPortfolio ? null : { portfolio }, ); return ( <div> <label> Portfolio:{' '} <select value={portfolio} onChange={e => setPortfolio(e.currentTarget.value)} > <option value="A">Portfolio A</option> <option value="B">Portfolio B</option> </select> </label> <CompanyGrid companies={companies} /> </div> ); } render(<PortfolioGrid />);
The example shows the same Company entities rendered through different portfolio lenses. Stable Entity fields are reused, while lens-dependent values are selected from separate Scalar cells.
- Schema.denormalize() takes a delegate -
denormalize(input, args, unvisit)→denormalize(input, delegate). Affects custom Schema implementations only. - Schema.normalize() takes a delegate -
normalize(input, parent, key, args, visit, delegate)→normalize(input, parent, key, delegate). Affects custom Schema implementations only.
Upgrade with the automated codemod:
npx jscodeshift -t https://dataclient.io/codemods/v0.18.js --extensions=ts,tsx,js,jsx src/
