Skip to main content

v0.10: Consistent Null Handling, URL Utilities

· 4 min read
Nathaniel Tucker
Creator of Reactive Data Client

This release focuses on consistency and extensibility. Null handling is now uniform across all schema types, making data transformations more predictable. New URL utilities enable custom URL construction and search parameter encoding.

class MyEndpoint<O extends RestGenerics = any> extends RestEndpoint<O> {
searchToString(searchParams) {
// Use qs library for complex nested object encoding
return qs.stringify(searchParams);
}
}
Migration guide

Breaking Changes:

Other Improvements:

Consistent null handling

null values are now consistently retained across all schema types. Previously, [] shorthand and schema.Array behaved differently when encountering null values. #2912

  • [] and schema.Array now behave identically
  • null values are retained everywhere (they were already retained in nested Entities)
  • undefined values are still filtered out

This change ensures more predictable behavior when working with APIs that explicitly return null to indicate absence of data versus undefined for missing fields.

URL Utilities

RestEndpoint.searchToString()

RestEndpoint.searchToString() enables custom encoding of search parameters. This is particularly useful for APIs that expect complex nested objects in query strings. #2919

For example, to encode complex objects using the qs library:

import { RestEndpoint, RestGenerics } from '@data-client/rest';
import qs from 'qs';

class MyEndpoint<O extends RestGenerics = any> extends RestEndpoint<O> {
searchToString(searchParams) {
return qs.stringify(searchParams);
}
}

getUrlBase, getUrlTokens

New exports getUrlBase and getUrlTokens provide the building blocks for custom RestEndpoint.url() implementations. #2919

import { getUrlBase, getUrlTokens } from '@data-client/rest';

// Parse path tokens for custom URL logic
const tokens = getUrlTokens('/users/:id/posts/:postId');
// => ['id', 'postId']

// Get base URL without path parameters
const base = getUrlBase('/users/:id');
// => '/users/'

DevToolsManager memory fix

The DevToolsManager action buffer is now limited to 100 entries, preventing memory leaks in long-running applications or those with frequent updates. 4e6a39e

Migration Guide

This upgrade requires updating all package versions simultaneously.

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

Null values in arrays

If your code relied on null values being filtered out of arrays, you'll need to handle this explicitly:

Before
import { Entity, schema, RestEndpoint } from '@data-client/rest';

class User extends Entity {
id = '';
name = '';
pk() { return this.id; }
}

const getUsers = new RestEndpoint({
path: '/users',
schema: new schema.Array(User),
});

// API response: [{ id: '1' }, null, { id: '2' }]
const usersWithoutNull = useSuspense(getUsers);
After
import { Entity, schema, RestEndpoint } from '@data-client/rest';

class User extends Entity {
id = '';
name = '';
pk() { return this.id; }
}

const getUsers = new RestEndpoint({
path: '/users',
schema: new schema.Array(User),
});

// API response: [{ id: '1' }, null, { id: '2' }]
const usersWithoutNull = useSuspense(getUsers).filter(Boolean);

This change aligns with how nested Entities already handled null values, making the behavior consistent across all schema types.

Upgrade support

As usual, if you have any troubles or questions, feel free to join our Chat or file a bug