Skip to content

Instantly share code, notes, and snippets.

@mohsen1
Created July 31, 2017 21:20

Revisions

  1. mohsen1 created this gist Jul 31, 2017.
    86 changes: 86 additions & 0 deletions HydratableStore.tsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,86 @@
    import * as React from 'react';
    import { computed } from 'mobx';
    import { inject, observer, Provider } from 'mobx-react';
    import { fromPromise } from 'mobx-utils';
    import {StaticRouter} from 'react-router-dom';
    import { Request, Response } from 'express';
    import * as ReactDOM from 'react-dom/server';

    interface Item {
    weight: number;
    }

    class HydratableStore {
    __hydration_promises: Promise<any>[] = [];
    waitForHydration() {
    return Promise.all(this.__hydration_promises);
    }
    }

    class Store extends HydratableStore {
    itemsPromise?: Promise<Item>;

    @hydratable @computed get item() {
    if (!this.itemsPromise) {
    this.itemsPromise = fetch('/item').then(res => res.json());
    }
    return this.itemsPromise;
    }

    toString() {

    }
    }


    @inject('store')
    @observer
    class ItemComp extends React.Component<{store?: Store}, {item: Item}> {
    state = { item: null }
    componentWillMount() {
    this.props.store.item.then(item => {
    this.setState({ item });
    });
    }
    render() {
    return <div>{this.state.item}</div>
    }
    }

    const App = () => <ItemComp />


    // in server
    export async function render(req: Request, res: Response) {
    const store = new Store();

    const app = (
    <Provider store={store}>
    <StaticRouter location={req.url}>
    <App />
    </StaticRouter>
    </Provider>
    )

    await store.waitForHydration();
    res.send(`
    <body>
    <div id="root">${ReactDOM.renderToString(app)}</div>
    <script>window.__store_state__ = ${serialize(store)}</script>
    </body>
    `);
    }



    function hydratable() {
    return function() {
    // grab the returned promise of the getter function and push it to __hydration_promises
    // of store instance. This requires store to inherit from HydratableStore
    // TODO
    }
    }

    function serialize(store: Store) {
    return ''
    }