Nau is a tool that makes Apollo Client more productive for users using Relay GraphQL Server Specification compliant backends.
- Make cache operations very easy
- Provide custom directives to write declaratively and improve productivity
- Support co-location of components and fragments by allowing a query to split into the fragments
- Support subscriptions
The tool aims to help frontend developers build frontend applications more quickly, with fewer bugs, and more efficiently.
Nau is a perfect fit with React, Apollo Client, GraphQL Code Generator, and TypeScript.
yarn add @kazekyo/nau
yarn add --dev @kazekyo/nau-graphql-codegen-preset
⚠️ The packages are currently under development. All version updates may have breaking changes.
See the example code.
You can write pagination and cache updates more easily using some GraphQL directives. 🚀
import { gql, useMutation, useSubscription } from '@apollo/client';
import { usePagination } from '@kazekyo/nau';
import * as React from 'react';
import {
AddItemMutationDocument,
ItemAddedSubscriptionDocument,
ItemRemovedSubscriptionDocument,
List_PaginationQueryDocument,
List_UserFragment
} from './generated/graphql';
import ListItem from './ListItem';
gql`
fragment List_user on User
@argumentDefinitions(count: { type: "Int", defaultValue: 2 }, cursor: { type: "String" })
@refetchable(queryName: "List_PaginationQuery") {
items(first: $count, after: $cursor) @pagination {
edges {
node {
...ListItem_item
}
}
}
...ListItem_user
}
mutation AddItemMutation($input: AddItemInput!, $connections: [String!]!) {
addItem(input: $input) {
item @prependNode(connections: $connections) {
...ListItem_item
}
}
}
subscription ItemAddedSubscription($connections: [String!]!) {
itemAdded {
item @prependNode(connections: $connections) {
...ListItem_item
}
}
}
subscription ItemRemovedSubscription {
itemRemoved {
id @deleteRecord(typename: "Item")
}
}
`;
const List: React.FC<{ user: List_UserFragment }> = ({ user }) => {
useSubscription(ItemAddedSubscriptionDocument, {
variables: {
connections: [user.items._connectionId],
},
});
useSubscription(ItemRemovedSubscriptionDocument);
const [addItem] = useMutation(AddItemMutationDocument);
const { nodes, hasNext, loadNext, isLoading } = usePagination(List_PaginationQueryDocument, {
id: user.id,
connection: user.items,
});
return (
<>
<div>
<button
onClick={() =>
void addItem({
variables: {
input: { itemName: 'new item', userId: user.id },
connections: [user.items._connectionId],
},
})
}
>
Add Item
</button>
</div>
<div>
{nodes.map((node) => {
return (
<div key={node.id}>
<ListItem user={user} item={node} />
</div>
);
})}
</div>
{hasNext && (
<button onClick={() => loadNext(2)} disabled={!hasNext}>
Load more
</button>
)}
</>
);
};
export default List;