Is it possible to use mobx with gatsby without using client side routing? I've taken a look at https://github.com/Shaid/gatsby-example-mobx but it uses react-router client side routing. I assume those routes won't be picked up by gatsby and created as static html files?
At the moment ive tried to wrap my layouts/index.js in <Provider> from mobx-react, and use @inject in pages/index.js but it won't work.
This works for me:
#gatsby-ssr.js
import { Provider, useStaticRendering } from "mobx-react";
import { renderToString } from "react-dom/server";
import MyStore from "../src/stores/MyStore";
exports.replaceRenderer = ({ bodyComponent, replaceBodyHTMLString }) => {
useStaticRendering(true);
const ProviderBody = () => (
<Provider Store={MyStore}>
{bodyComponent}
</Provider>
);
replaceBodyHTMLString(renderToString(<ProviderBody />));
};
# gatsby-browser.js
import { Router } from "react-router-dom";
import { Provider } from "mobx-react";
import MyStore from "../src/stores/MyStore";
exports.replaceRouterComponent = ({ history }) => {
return ({ children }) => (
<Provider Store={MyStore}>
<Router history={history}>{children}</Router>
</Provider>
);
};
#component.js
@inject("Store")
@observer
export default class MyComponent extends Component {
...
}
# src/stores/MyStore.js
import {observable} from 'mobx';
export class MyStore {
@observable myState = {};
....
}
@TomiTakussaari thanks. Interesting approach. I'll have a look at it 👍
@TomiTakussaari when i run build, throw error " MobX injector: Store 'store' is not available! Make sure it is provided by some Provider"
Do you have example code ?
I migrated my mobx-using-gatsby project to Next.js, because I needed dynamic pages, but I think this approach should still work with Gatsby..
Perhaps there should be "using-mobx" example in Gatsby, let's see if i'll find time and motivation for it
I think the code of gatsby-ssr is Useless,because gatsby develop is ok,and gatsby build is not work.
at last, I move Provider to layouts/index.js
@TomiTakussaari prop variable MyStore is not in scope in your gatsby-browser.js.
Mind correcting the snippet for reference? 😁
@rongierlach Yeah, I left defining Store out previously for some reason. Added it there now.
Did not test it though, so there might be typos etc.
I'll try to find time to create PR with mobx example later.
@Cacivy I created my Mobx implementation by following Gatsby's Redux example.
You need both gatsby-ssr & gatsby-browser.js for it work in build, develop & actual browser.
Atleast that's what I found out when creating it originally, have'nt tested if Gatsbys ways have changed since that.
I am having the same issue. Works fine for development, but the build fails, saying my store is not provided despite the replaceRouterComponent implementation.
I think (for me at least), this is occurring due to also using gatsby-plugin-styled-components, which uses the replaceRouterComponent API as well. According to https://www.gatsbyjs.org/docs/ssr-apis/, only one plugin can use this API.
I worked around this by removing the styled components plugin, and rolling its implementation into my own custom gatsby-ssr.js
import * as React from 'react';
import { Provider, useStaticRendering } from 'mobx-react';
import { renderToString } from 'react-dom/server';
import { ServerStyleSheet, StyleSheetManager } from 'styled-components';
import { BreweryStore } from 'Stores/BreweryStore';
exports.replaceRenderer = ({
bodyComponent,
replaceBodyHTMLString,
setHeadComponents,
}) => {
useStaticRendering(true);
const sheet = new ServerStyleSheet()
const app = (
<StyleSheetManager sheet={sheet.instance}>
<Provider BreweryStore={BreweryStore}>
{bodyComponent}
</Provider>
</StyleSheetManager>
)
const body = renderToString(app)
replaceBodyHTMLString(body)
setHeadComponents([sheet.getStyleElement()])
};
Using setup suggested by @TomiTakussaari
keep getting this issue during gatsby build:
error Building static HTML for pages failed
See our docs page on debugging HTML builds for help https://goo.gl/yL9lND
40 | var args = [a, b, c, d, e, f];
41 | var argIndex = 0;
> 42 | error = new Error(format.replace(/%s/g, function () {
| ^
43 | return args[argIndex++];
44 | }));
45 | error.name = 'Invariant Violation';
WebpackError: Minified React error #143; visit https://reactjs.org/docs/error-decoder.html?invariant=143 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
React error #143 is React.Children.only expected to receive a single React element child.
I simplified all my components and pages down to a minimum and still can't figure out where am I passing wrong components. I'm starting to suspect it's due to MobX integration…
Any ideas what could be wrong?
Ok. Fixed it by moving useStaticRendering(true) outside of replaceRenderer function, in gatsby-ssr.js
import React from 'react'
import { Provider, useStaticRendering } from 'mobx-react'
import { renderToString } from 'react-dom/server'
import stores from './src/stores'
useStaticRendering(true)
exports.replaceRenderer = ({ bodyComponent, replaceBodyHTMLString }) => {
const ProviderBody = () => (
<Provider {...stores}>{bodyComponent}</Provider>
)
replaceBodyHTMLString(renderToString(<ProviderBody/>))
}
Due to the high volume of issues, we're closing out older ones without recent activity. Please open a new issue if you need help!
@KyleAMathews and to whom it may concern. i saw this issue being bounced around a bit so i took a crack at it. Grabbed the example from redux and implemented it using mobx i have a working example in here . If you guys want it add that to the examples. Thanks in advance
Most helpful comment
@KyleAMathews and to whom it may concern. i saw this issue being bounced around a bit so i took a crack at it. Grabbed the example from redux and implemented it using mobx i have a working example in here . If you guys want it add that to the examples. Thanks in advance