Using hooks with class components
Hooks are great, but many of us are working with existing codebases or libraries with class based components. Some might be easy to migrate but others might be more diffcult. Should this block you from adopting Reactive Data Client? Of course not!
Using the simple hook-hoc interop library we can create Higher Order Components from hooks quite easily. This enables us to easily replace any existing HOC with ease.
Install hook-hoc
- NPM
- Yarn
- pnpm
- esm.sh
yarn add hook-hoc
npm install --save hook-hoc
pnpm add hook-hoc
<script type="module">
import * from 'https://esm.sh/hook-hoc';
</script>
Use with class
import { PureComponent } from 'react';
import withHook from 'hook-hoc';
import { useSuspense } from '@data-client/react';
import { User, UserResource } from './resources/User';
class Profile extends PureComponent<{
id: number;
user: User;
friends: User[];
}> {
//...
}
export default withHook(({ id }: { id: number }) => {
const user = useSuspense(UserResource.get, { id });
const friends = useSuspense(UserResource.getList, { friendid: id });
return { user, friends };
})(Profile);
Here you can see the return value of the function you pass in gets injected into the props of the component you wrap.
Extracting the function
You might notice the function we pass to withHook() is a function that calls
hooks. That makes it a hook by definition. To make this detectable by the rules of hooks
and also potentially reusable, let's move it out to a named function:
import { PureComponent } from 'react';
import withHook from 'hook-hoc';
import { useSuspense } from '@data-client/react';
import { User, UserResource } from './resources/User';
function useProfile({ id }: { id: number }) {
const user = useSuspense(UserResource.get, { id });
const friends = useSuspense(UserResource.getList, { friendid: id });
return { user, friends };
}
class Profile extends PureComponent<{
id: number;
user: User;
friends: User[];
}> {
//...
}
export default withHook(useProfile)(Profile);
Filters, debounce and more
Often times you'll be doing a bit more than just retrieving the data. We can do all of that extra work in the hook we just created. Here we'll add some client-side filtering as well as debouncing the requests themselves.
You can combine any hooks here - the sky's the limit.
import { useSuspense, useDebounce } from '@data-client/react';
import { UserResource } from './resources/User';
function useProfile({ id }: { id: number }) {
const debouncedId = useDebounce(id, 150);
const user = useSuspense(UserResource.get, { id });
const friends = useSuspense(UserResource.getList, { friendid: id });
const realFriends = friends.filter(friend => friend.isReal);
return { user, friends: realFriends };
}
// rest of file...