3.4.0-canary.8 • Published 10 days ago

mst-query v3.4.0-canary.8

Weekly downloads
-
License
MIT
Repository
github
Last release
10 days ago

Query library for mobx-state-tree

Features

  • Automatic Normalization
  • Garbage Collection
  • Use with any backend (REST, GraphQL, whatever!)
  • Optimistic UI with automatic rollback
  • Infinite Scroll + Pagination Queries
  • Request Argument Validation
  • Abort Requests
  • Client Models

Basic Usage

First, create some models, a query and a store...

import { types } from 'mobx-state-tree';
import { createQuery, MstQueryRef, createRootStore, createModelStore } from 'mst-query';

const UserModel = types.model('UserModel', {
    id: types.identifier,
    name: types.string,
    age: types.number,
});

const MessageModel = types.model('MessageModel', {
    id: types.identifier,
    message: types.string,
    created: types.Date,
    createdBy: MstQueryRef(UserModel),
});

const MessageQuery = createQuery('MessageQuery', {
    data: MstQueryRef(MessageModel),
    request: types.model({ id: types.string }),
    endpoint: ({ request }) => {
        const { id } = request;
        return fetch(`/api/message/${id}`).then((res) => res.json());
    }
});

const RootStore = createRootStore({
    messageStore: types.optional(createModelStore(MessageModel), {}),
    userStore: types.optional(createModelStore(UserModel), {}),
}).props({
    messageQuery: types.optional(MessageQuery, {})
}).actions(self => ({
    getMessage: flow(function* (request) {
        self.messageQuery.run({ request });
    })
}));

...then use the query in a React component!

import { useQuery } from 'mst-query';
import { observer } from 'mobx-react';

const queryClient = new QueryClient({ RootStore });
const { QueryClientProvider, useRootStore } = createContext(queryClient);

const useMessageQuery = (id: string) => {
    const rootStore = useRootStore();
    return useQuery(rootStore.messageQuery, rootStore.getMessage {
        request: { id },
    });
};

const MesssageView = observer((props) => {
    const { id } = useParams();

    const { data, error, isLoading } = useMessageQuery(id);
    if (error) {
        return <div>An error occured...</div>;
    }
    if (isLoading) {
        return <div>Loading...</div>;
    }
    return <div>{data.message}</div>;
});

const App = observer((props) => {
    return (
        <QueryClientProvider>
            <MessageView id={props.id} />
        </QueryClientProvider>
    );
});

Installation

npm install --save mst-query mobx-state-tree

Models

In general, models can be created as usual. The main difference is how we handle references.

MstQueryRef

A custom reference that replaces types.reference.

import { types } from 'mobx-state-tree';

const UserModel = types.model({
    id: types.identifier, // a normal identifier
    name: types.string.
    age: types.number
});

const MessageModel = types.model({
    message: types.string,
    createdBy: MstQueryRef(UserModel)
});

Since data can be garbage collected in mst-query, MstQueryRef doesn't throw if it cannot find a suitable model in the internal cache. Instead, it simply returns the id as a string, allowing us to fetch data for this model again.

Queries

createQuery

A query is just a mobx-state-tree model, but with special properties, called a QueryModel. Here's an example of a query that fetches a list of messages.

import { types } from 'mobx-state-tree';
import { createQuery } from 'mst-query';
import { MessageModel } from './models';

const MessageListQuery = createQuery('MessageListQuery', {
    data: types.array(MstQueryRef(MessageModel)),
    request: types.model({ filter: '' }),
});

The first argument to createQuery is the name of this query. The second is an option object that controls how this query recevies (data) and transmits (request) data. TODO: endpoint

useQuery

import { useQuery } from 'mst-query';
import { observer } from 'mobx-react';
import { MessageQuery } from './MessageQuery';

const MesssageView = observer((props) => {
    const { id, initialData, result } = props;
    const {
        data,
        error,
        isLoading,
        isFetched,
        isRefetching,
        isFetchingMore,
        query,
        refetch,
        cachedAt,
    } = useQuery(MessageQuery, {
        request: { id },
        enabled: true,
        initialData: initialData,
        onFetched(data, self) {},
        onSuccess(data, self) {},
        onError(data, self) {},
        staleTime: 0,
    });
    if (error) {
        return <div>An error occured...</div>;
    }
    if (isLoading) {
        return <div>Loading...</div>;
    }
    return <div>{data.message}</div>;
});

Paginated and infinite lists

useInfiniteQuery

import { useInfiniteQuery } from 'mst-query';
import { observer } from 'mobx-react';
import { MessageQuery } from './MessageQuery';

const MesssageView = observer((props) => {
    const { id, cachedData } = props;
    const { data, error, isLoading, query } = useInfiniteQuery(MessageQuery, {
        request: { id },
    });

    useEffect(() => {
        query.run();
    }, []);

    if (error) {
        return <div>An error occured...</div>;
    }
    if (isLoading) {
        return <div>Loading...</div>;
    }
    return <div>{data.message}</div>;
});

queryMore

// TODO: Example

The difference between query and queryMore is that the latter does not automatically merge it's result to the underlying query. This allows you to easily control how the data is appended to your list. It also means mst-query supports many different forms of pagination (offset-based, cursor-based, page-number-based) out of the box.

Mutations

createMutation

// TODO: Example

useMutation

// TODO: Example

Optimistic updates

// TODO: Example, write docs

Client models

Cache

// TODO: Write docs

rootStore

3.4.0-canary.8

10 days ago

3.4.0-canary.7

19 days ago

3.4.0-canary.5

20 days ago

3.4.0-canary.6

20 days ago

3.4.0-canary.4

1 month ago

3.4.0-canary.3

1 month ago

3.4.0-canary.2

3 months ago

3.4.0-canary.1

3 months ago

3.4.0-canary.0

3 months ago

3.3.3

3 months ago

3.3.2

3 months ago

3.3.1

4 months ago

3.3.0

4 months ago

3.2.1

4 months ago

3.2.0

4 months ago

3.1.7

7 months ago

3.1.6

7 months ago

3.1.5

7 months ago

3.1.4

8 months ago

3.1.8

7 months ago

3.1.3

8 months ago

3.1.2

8 months ago

3.1.1

8 months ago

3.1.0

8 months ago

3.0.4

11 months ago

3.0.3

11 months ago

3.0.5

10 months ago

2.0.7

1 year ago

3.0.0-beta.1

1 year ago

3.0.0-beta.3

1 year ago

3.0.0-beta.2

1 year ago

3.0.0-beta.5

1 year ago

3.0.0-beta.4

1 year ago

3.0.0-beta.7

1 year ago

3.0.0-beta.6

1 year ago

3.0.0-beta.9

1 year ago

3.0.0-beta.8

1 year ago

3.0.2

12 months ago

3.0.1

12 months ago

3.0.0

1 year ago

3.0.0-beta.10

1 year ago

2.0.3

1 year ago

2.0.2

1 year ago

2.0.5

1 year ago

2.0.4

1 year ago

2.0.6

1 year ago

2.0.1

1 year ago

2.0.0

1 year ago

3.0.0-beta.0

1 year ago

1.1.6

1 year ago

2.0.0-alpha.4

2 years ago

1.1.4

2 years ago

1.1.3

2 years ago

1.1.2

2 years ago

2.0.0-beta.1

2 years ago

1.1.1

2 years ago

2.0.0-alpha.3

2 years ago

2.0.0-alpha.2

2 years ago

1.1.0

2 years ago

1.1.0-alpha.5

2 years ago

1.1.0-alpha.6

2 years ago

1.1.0-alpha.4

2 years ago

1.1.0-alpha.3

2 years ago

1.1.0-alpha.1

2 years ago

1.1.0-alpha.2

2 years ago

1.1.0-alpha.0

2 years ago

1.0.10

2 years ago

1.0.9

2 years ago

1.0.8

2 years ago

1.0.7

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago

1.0.6

2 years ago

1.0.4

2 years ago

1.0.3

2 years ago

0.10.1

3 years ago

0.10.2

3 years ago

0.10.3

3 years ago

0.10.4

3 years ago

0.10.0

3 years ago

0.9.1

3 years ago

0.9.0

3 years ago

0.7.17

3 years ago

0.8.0

3 years ago

0.7.16

3 years ago

0.7.15

3 years ago

0.7.14

3 years ago

0.7.13

3 years ago

0.7.11

3 years ago

0.7.10

3 years ago

0.7.9

3 years ago

0.7.12

3 years ago

0.7.8

3 years ago

0.7.7

3 years ago

0.7.6

3 years ago

0.7.5

3 years ago

0.7.2

3 years ago

0.7.4

3 years ago

0.7.3

3 years ago

0.7.1

3 years ago

0.7.0

3 years ago

0.6.3

3 years ago

0.6.2

3 years ago

0.6.1

3 years ago

0.6.0

3 years ago

0.4.7

3 years ago

0.5.0

3 years ago

0.5.1

3 years ago

0.4.6

3 years ago

0.4.5

3 years ago

0.4.4

3 years ago

0.4.3

3 years ago

0.4.2

3 years ago

0.4.1

3 years ago

0.3.4

3 years ago

0.3.3

3 years ago

0.3.2

3 years ago

0.3.1

3 years ago

0.3.0

3 years ago

0.2.1

3 years ago

0.2.0

3 years ago

0.1.0

3 years ago