Skip to main content

Entities 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 Entity 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

Fixtures
GET http://fakeapi.com/article/5
{"id":"5","author":{"id":"123","name":"Jim"},"content":"Happy day","contributors":[{"id":"100","name":"Eliza"}]}
api/Post.ts
export class User extends Entity {
id = '';
name = '';
pk() {
return this.id;
}
}
export class Post extends Entity {
readonly id: number | undefined = undefined;
readonly author: User = User.fromJS({});
readonly content: string = '';
readonly contributors: User[] = [];
static schema = {
author: User,
contributors: [User],
};
pk() {
return `${this.id}`;
}
}
export const getPost = new RestEndpoint({
urlPrefix: 'http://fakeapi.com',
path: '/article/:id',
schema: Post,
});
PostPage.tsx
import { getPost } from './api/Post';
function PostPage() {
const post = useSuspense(getPost, { id: '5' });
return (
<div>
<p>
{post.content} - <cite>{post.author.name}</cite>
</p>
<div>Contributors: {post.contributors.map(user => user.name)}</div>
</div>
);
}
render(<PostPage />);
Live Preview
Loading...
Store
    • {} 0 keys
      • {} 0 keys
        • {} 0 keys
          • {} 0 keys
            • {} 0 keys
              • 0

            Circular dependencies

            If both Entities are in distinct files, this must be handled with care.

            If two or more Entities include each other in their schema, you can dynamically override one of their schema to avoid circular imports.

            api/Article.ts
            import { Entity } from '@rest-hooks/rest';
            import { User } from './User';

            export class Article extends Entity {
            readonly id: number | undefined = undefined;
            readonly content: string = '';
            readonly author: User = User.fromJS({});
            readonly contributors: User[] = [];

            pk() {
            return this.id?.toString();
            }

            static schema: { [k: string]: Schema } = {
            author: User,
            contributors: [User],
            };
            }

            // we set the schema here since we can correctly reference Article
            User.schema = {
            posts: [Article],
            };
            api/User.ts
            import { Entity } from '@rest-hooks/rest';
            import type { Article } from './Article';
            // we can only import the type else we break javascript imports
            // thus we change the schema of UserResource above

            export class User extends Entity {
            readonly id: number | undefined = undefined;
            readonly name: string = '';
            readonly posts: Article[] = [];
            readonly createdAt: Date = new Date(0);

            pk() {
            return this.id?.toString();
            }

            static schema: Record<string, Schema | Date> = {
            createdAt: Date,
            };
            }