redux-suspense-selector
v0.1.0
Published
Read resolved Redux selector resources through React Suspense.
Readme
redux-suspense-selector
redux-suspense-selector lets React Suspense wait on Redux selector state.
It is not a data fetching library. It does not own HTTP calls, cache policy, retry policy, invalidation, or UI state meaning.
Core Idea
Resource unresolved -> suspend
Resource resolved -> return valuetype Resource<T> = { resolved: false } | { resolved: true; value: T };resolved: true only means the success subtree has the value it requires. It does not mean the
screen is not refreshing, the data is fresh, or the last request succeeded.
API
import { resolved, unresolved, useSuspenseSelector } from "redux-suspense-selector";
const resource = unresolved<Order[]>();
const loaded = resolved<Order[]>(orders);
const useAppSuspenseSelector = useSuspenseSelector.withTypes<RootState>();const orders = useAppSuspenseSelector(selectOrdersResource);useSuspenseSelector takes a selector that returns Resource<T> and returns T.
If the resource is unresolved, it throws a promise that resolves when the selector becomes
resolved in the Redux store.
Usage Pattern
Keep screen state and required data separate.
type OrdersState = {
errorMessage: string | null;
isLoading: boolean;
orders: Resource<OrderListItem[]>;
};Name selectors that return Resource<T> with a Resource suffix.
export const selectOrderListState = (state: RootState): OrdersState => state.orders;
export const selectOrdersResource = (state: RootState): Resource<OrderListItem[]> =>
state.orders.orders;Read screen state with normal selectors and required data with Suspense selectors.
function OrderList() {
const { errorMessage, isLoading } = useAppSelector(selectOrderListState);
const orders = useAppSuspenseSelector(selectOrdersResource);
return <OrdersScreen orders={orders} isLoading={isLoading} errorMessage={errorMessage} />;
}Boundaries
This package does not decide:
- when to fetch
- how to map DTOs
- whether stale data is acceptable
- whether an error is blocking
- whether failed refresh should clear existing data
- how loading and error should appear in the UI
Keep those policies in Redux slices, selectors, and thunks.
Examples
- orders: minimal slice, thunk, fallback, and success subtree.
- filtered-orders: derived
Resource<T>selector. - async-thunk-orders: RTK
createAsyncThunkwithResource<T>stored infulfilled.
Development
pnpm install
pnpm check