# Client Side Sorting

Here we have an API that sorts based on the `orderBy` field. By wrapping our [Collection](https://dataclient.io/rest/api/Collection.md)
in a [Query](https://dataclient.io/rest/api/Query.md) that sorts, we can ensure we maintain the correct order after [pushing](https://dataclient.io/rest/api/RestEndpoint.md#push)
new posts.

Our example code starts sorting by `title`. Try adding some posts and see them inserted in the correct sort
order.

```ts title="getPosts" {17-24}
import { Collection, Entity, Query, RestEndpoint } from '@data-client/rest';

export class Post extends Entity {
  id = '';
  title = '';
  group = '';
  author = '';
}

export const getPosts = new RestEndpoint({
  path: '/:group/posts',
  searchParams: {} as { orderBy?: string; author?: string },
  schema: new Query(
    new Collection([Post], {
      nonFilterArgumentKeys: /orderBy/,
    }),
    (posts, { orderBy } = {}) => {
      if (orderBy) {
        return [...posts].sort((a, b) =>
          a[orderBy].localeCompare(b[orderBy]),
        );
      }
      return posts;
    },
  ),
});
```

```tsx title="NewPost"
import { useController, useLoading } from '@data-client/react';
import { getPosts } from './getPosts';

export default function NewPost({ author }: Props) {
  const ctrl = useController();

  const [handlePress, loading] = useLoading(async e => {
    if (e.key === 'Enter') {
      const title = e.currentTarget.value;
      e.currentTarget.value = '';
      await ctrl.fetch(
        getPosts.push,
        { group: 'react' },
        {
          title,
          author,
        },
      );
    }
  });

  return <TextInput onKeyDown={handlePress} loading={loading} placeholder="Post title" />;
}
interface Props {
  author: string;
}
```

```tsx title="PostList" {8}
import { useSuspense } from '@data-client/react';
import { getPosts } from './getPosts';
import NewPost from './NewPost';

export default function PostList({ author }: Props) {
  const posts = useSuspense(getPosts, {
    author,
    orderBy: 'title',
    group: 'react',
  });
  return (
    <div>
      {posts.map(post => (
        <div key={post.pk()}>{post.title}</div>
      ))}
      <NewPost author={author} />
    </div>
  );
}
interface Props {
  author: string;
}
```

```tsx title="UserList"
import PostList from './PostList';

function UserList() {
  const users = ['bob', 'clara'];
  return (
    <div>
      {users.map(user => (
        <section key={user}>
          <h3>{user}</h3>
          <PostList author={user} />
        </section>
      ))}
    </div>
  );
}
render(<UserList />);
```
