Resources with nested structure
Say you have a foreignkey author, and an array of foreign keys to contributors.
First we need to model what this will look like by adding members to our Resource definition. These should be the primary keys of the entities we care about.
Next we'll provide a definition of nested members in the schema member.
static schema
resources/ArticleResource.ts
import { Resource, AbstractInstanceType } from '@rest-hooks/rest';
import { UserResource } from 'resources';
export default class ArticleResource extends Resource {
readonly id: number | undefined = undefined;
readonly content: string = '';
readonly author: UserResource = UserResource.fromJS({});
readonly contributors: number[] = [];
pk() {
return this.id?.toString();
}
static urlRoot = 'http://test.com/article/';
static schema = {
author: UserResource,
contributors: [UserResource],
};
}
ArticleList.tsx
import { useResource } from 'rest-hooks';
import ArticleResource from 'resources/ArticleResource';
export default function ArticleList({ id }: { id: number }) {
const articles = useResource(ArticleResource.list(), { id });
return (
<React.Fragment>
{articles.map(article => (
<>
<ArticleInline key={article.pk()} article={article} />
<UserPreview user={article.user} />
</>
))}
</React.Fragment>
);
}
function UserPreview({ user }: { user: UserResource }) {
return <span>{user.username} {user.email}</span>
}
Circular dependencies
If both Resources are in distinct files, this must be handled with care.
If two or more Resources include each other in their schema, you can dynamically override one of their schema to avoid circular imports.
resources/ArticleResource.ts
import { Resource, AbstractInstanceType } from '@rest-hooks/rest';
import { UserResource } from 'resources';
export default class ArticleResource extends Resource {
readonly id: number | undefined = undefined;
readonly content: string = '';
readonly author: UserResource = UserResource.fromJS({});
readonly contributors: number[] = [];
pk() {
return this.id?.toString();
}
static urlRoot = 'http://test.com/article/';
static schema = {
author: UserResource,
contributors: [UserResource],
};
}
// we set the schema here since we can correctly reference ArticleResource
UserResource.schema = {
posts: [ArticleResource],
};
resources/UserResource.ts
import { Resource } from '@rest-hooks/rest';
import type { ArticleResource } from 'resources';
// we can only import the type else we break javascript imports
// thus we change the schema of UserResource above
export default class UserResource extends Resource {
readonly id: number | undefined = undefined;
readonly name: string = '';
readonly posts: ArticleResource[] = [];
pk() {
return this.id?.toString();
}
static urlRoot = 'http://test.com/user/';
}