Implicit Data Fetching

Common data fetching pattern with gstate.

  1. Call async functions to fetch data from remote server.
  2. Result use to update state.
  3. Components would be notified to re-render with updated state.

The explicit data fetching sample:

var service = axios.create({
    baseURL: "https://hacker-news.firebaseio.com/v0"
});

function fetchStories(state, type, skip = 0, limit = 10) {
    let ids = await service.get(`/${type}.json`).then(resp => resp.data);
    ids = ids.slice(skip, skip + limit);

    var stories = [];

    for (var i = 0; i < ids.length; i++) {
        const item = await service
            .get(`/item/${ids[i]}.json`)
            .then(resp => resp.data);
        stories.push(item);
    }

    state.set({ [type]: stories });
}

page("/", () => {
    const type = "topstories";
    const data = fetchStories(state, type);
    browserRender(stories(type), { state, data });
});

page("/new", () => {
    const type = "newstories";
    const data = fetchStories(state, type);
    browserRender(stories(type), { state, data });
});

page("/show", () => {
    const type = "showstories";
    const data = fetchStories(state, type);
    browserRender(stories(type), { state, data });
});

page("/ask", () => {
    const type = "askstories";
    const data = fetchStories(state, type);
    browserRender(stories(type), { state, data });
});
page("*", () => {
    browserRender(NotFound);
});

page({ click: false });

function browserRender(View, props = {}) {
    const rootEl = document.getElementById("root");
    if (props.data && props.data.then) {
        props.data
            .then()
            .then(
                () =>
                    ReactDOM.render(
                        <View {...props} loading={false} />,
                        rootEl
                    ),
                error =>
                    ReactDOM.render(<View {...props} loading={error} />, rootEl)
            );
        ReactDOM.render(<View {...props} loading={true} />, rootEl);
    } else {
        ReactDOM.render(<View {...props} />, rootEl);
    }
}

Implicit data fetching

The pattern use GState's onWatchCallback to call fetching function on-demand.

  1. Components use declarative data pattern to retrieve required data.
  2. If the declarative data touch the path registered with onWatchCallback, the callback will be triggered once.
  3. Then the callback call async functions to fetch data from remote server.
  4. Result use to update state.
  5. Components would be notified to re-render with updated state.

The implicit data fetching:

state.onWatchCallback("pages", function(query) { // hook on pages
    state.set({ loading: true });

    const type = Object.keys(query)[0];

    //Fetch data and update state for Components.
    fetchStories(state, type).then(
        () => state.set({ loading: false }),
        err => state.set({ loading: err })
    );
});

page("/", () => {
    const type = "topstories";
    browserRender(stories(type), { state });
});

const stories = type => {
    // the query will trigger onWatchCallback on pages.
    return gstate(
        {
            pages: { 
                [type]: {
                    _: 1
                }
            },
            loading: 1
        },
        (props, data) => {
            const pages = data.pages || {};
            return <Stories items={pages[type]} loading={data.loading} />;
        }
    );
};

Notices

  1. onWatchCallback will triggered once for each query. The same query could retrieved data many times without trigger the callback again. To refetch data, you should re-mount the component or re-query (gstate HoC should provide refetch function to re-query)
  2. You should implement additional flag to prevent multiple components trigger the same callbacks.
  3. You could use the query parameter of callback function to implement smarter data fetching strategics. For example, convert query into GraphQL query.
  4. You could use state anchoring to implement relationship data fetching strategics. For example, the pages callback will fetching pages data and anchor page's owner to users path. When components try to read page's owner data, it will trigger users callback which fetching users data

results matching ""

    No results matching ""