Allow mocking and typing
See original GitHub issueswr looks really cool 👍
I played around with something similar for request-registry recently.
What I miss in swr
over request-registry is the ability to define typings, dependencies and to mock
I would love to know what you think about those features.
Define typings once per endpoint
In request registry you define endpoints e.g.:
import { createGetEndpoint } from "request-registry";
// Define a service endpoint to load user information
const userEndpoint = createGetEndpoint<{id: string}, {name: string, age: number}>({
url: keys => `http://example.com/user/${keys.id}`
});
Then you can use them from a hook e.g.
import {useGetEndPointSuspendable} from 'request-registry-react';
const UserDetails = props => {
const { name } = useGetEndPointSuspendable(userEndpoint, { id: props.id });
return <div>{name}</div>;
};
It also works without suspense similar to the swr api:
const UserDetails = props => {
const endpointState = useGetEndPoint(userEndpoint, { id: props.id });
if (!endpointState.hasData) {
return <div>Loading...</div>;
}
const { name } = endpointState.value;
return <div>{name}</div>;
};
This allows autocomplete and type checking for endpointState.value
without writing additional endpoint specific types inside the UserDetails component.
Dependencies
Endpoints can also cause mutations e.g.:
import { createPostEndpoint } from "request-registry";
// Define a mutation endpoint
const mutateUser = createPostEndpoint<{id: string}, {name: string}, {}>({
url: keys => `http://example.com/user/${keys.id}`
// Invalidate all userEndpoint endpoints (similar to your trigger broadcast)
afterSuccess: () => userEndpoint.refresh()
});
// now for example inside an eventHandler
<button onClick={async () => {
const newName = data.name.toUpperCase()
// update user 4 and rerender all components which rely on user 4 data:
await mutateUser(newName)
}}>
Mocking
For unit tests and storybook we sometimes want to tryout specific scenarios and want to mock backend responses.
// Define your mock data for getUserName
// Typescript will tell you if the mock data doesn't match the types for
// getUserName
const userJoeMock = createMockEndpoint(getUserName, async () => ({
name: 'Joe',
}));
Now in any unit test or story you can activate the mock:
// Activate mock:
userJoeMock.activate();
// Deactivate mock:
userJoeMock.clear();
There are more utils around this but maybe this is enough to get the basic idea.
I would love to know what you think about those features. 😃
Issue Analytics
- State:
- Created 4 years ago
- Reactions:1
- Comments:10 (6 by maintainers)
I think you could create a custom hook using SWR internally and define the types there.
Something like this, and if you move this custom hook to another file you could mock it in your tests.
In just you could do:
Something like that will mock useUser module and let you mock the implementation to return fake data immediately, you could also run
mockImplementation
multiple times to change what it will return.