Reputation: 112777
When using MobX with React you can create a new Store
instance on a class component instance like so:
const { extendObservable } = mobx;
const { Observer } = mobxReact;
class Store {
constructor() {
console.log("Created a store");
extendObservable(this, {
count: 0
});
}
}
class App extends React.Component {
store = new Store();
render() {
const { store } = this;
return (
<Observer>
{() => <button onClick={() => ++store.count}>{store.count}</button>}
</Observer>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/[email protected]/lib/mobx.umd.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/index.min.js"></script>
<div id="root"></div>
When translating this to a function component it still works, but a new Store
instance is created every render, which will not be used. This is not only wasteful, but can have undesired behaviour if the constructor contains additional logic.
const { extendObservable } = mobx;
const { observer, useObservable } = mobxReact;
class Store {
constructor() {
console.log("Created a store");
extendObservable(this, {
count: 0
});
}
}
const App = observer(() => {
const store = useObservable(new Store());
return <button onClick={() => ++store.count}>{store.count}</button>
});
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/[email protected]/lib/mobx.umd.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/index.min.js"></script>
<div id="root"></div>
Is there a way to just create one single Store
instance on first render in a function component?
Upvotes: 3
Views: 2244
Reputation: 112777
Instead of using the useObservable
hook we can use the useState
hook with a function that returns a new Store
as argument. This function will only be invoked once on first render which will make it so only one Store
instance is ever created.
const { useState } = React;
const { extendObservable } = mobx;
const { observer, useObservable } = mobxReact;
class Store {
constructor() {
console.log("Created a store");
extendObservable(this, {
count: 0
});
}
}
const App = observer(() => {
const [store] = useState(() => new Store());
return <button onClick={() => ++store.count}>{store.count}</button>
});
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/[email protected]/lib/mobx.umd.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/index.min.js"></script>
<div id="root"></div>
Upvotes: 3