useData
The useData hook
This hook allows subscription and full control over a state, and represents the API that you will be using with the most.
tip
useData uses the same signature as useAsync documented in its section.
This means that it accepts the same parameters and returns the same shape.
Please refer to useAsync documentation.
Its signature is:
function useData<TData, TArgs, TError, TSelection = State<TData, TArgs, TError>>(
config: MixedConfig<TData, TArgs, TError, TSelection>,
deps: any[] = []
): UseDataResult<TData, TArgs, TError> {
// [Not Native Code]
}
// used like this:
const result = useData(config, deps);
Differences from useAsync
The major difference is that useData will never return a pending or error
states.
useDatawill suspend if the status ispendinguseDatawill throw the error if status iserror
This means that useData assumes you are:
- Using a React
Error Boundaryto display errors if applied. - Using
Suspenseto display pending states (with or withoutTransition). - Or, you are working with a total synchronous state that's not supposed to error.
danger
If you work with suspense, it is important to give a key to your states.
Because if the tree suspends, React will reset everything and will result in creating a new state everytime, and thus, an infinite loop.
Example
Async
async function fetchUsers({ signal }: ProducerProps<User[]>) {
// artificially delayed by 500ms
await new Promise((res) => setTimeout(res, 1000));
return await API.get("/users", { signal }).then(({ data }) => data);
}
function Details() {
const { data, source } = useData({
lazy: false,
key: "user-details",
producer: fetchUsers,
});
return (
<div className="App">
<button onClick={() => source.run()}>
Fetch users
</button>
{data && (
<ul>
<summary>Users list:</summary>
{data.map((user: User) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
)}
</div>
);
}
function App() {
return (
<Suspense fallback="Suspense fallback ... pending">
<Details />
</Suspense>
);
}
Counter
export default function App() {
const {
data,
source: { setData },
} = useData({
initialValue: 0,
});
return (
<div>
<button onClick={() => setData((prev) => prev! - 1)}>Decrement</button>
<span>{data}</span>
<button onClick={() => setData((prev) => prev! + 1)}>Increment</button>
</div>
);
}