Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
How to hydrate stores in the server with MobX
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 ''
}
@elado

This comment has been minimized.

Copy link

elado commented Aug 1, 2017

        this.props.store.item.then(item => {
            this.setState({ item });
        });

how do you react on store.item changes? keeping it in state won't re-render when there are property changes (I think, might be wrong) and definitely won't re-render when store.item becomes null (as a result of another operation)

I think we should stick to read store directly or read mobx objects from props, not state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.