ReactJS and MobX runtime style changes

I Decided to do a Proof of Concept of how I could allow for runtime application style changes using MobX in a ReactJS setup. This would allow the user to navigate to an area in an app, and choosing a desired application theme (Light/Dark), without requiring an app refresh.

It turned out, that its amazingly easy using MobX.

Create a MobX store where you maintain application styles. Lets call this store StyleStore.js and put it in a stores folder inside src.

import { observable, action, useStrict } from 'mobx';

useStrict(true);

class StyleStore {

 /**
 * ApplicationBar Styles.
 */
 @observable applicationBarStyle = {
 height: 40,
 backgroundColor: '#303030',
 color: '#ffffff'
 }

 /**
 * UI Handle to change theme to dark.
 */
 @action switchToDarkTheme() {
 this.applicationBarStyle = {
 ...this.applicationBarStyle,
 backgroundColor: '#303030',
 color: '#ffffff'
 }
 }

 /**
 * UI Handle to change theme to light.
 */
 @action switchToLightTheme() {
 this.applicationBarStyle = {
 ...this.applicationBarStyle,
 backgroundColor: '#EEEEEE',
 color: '#333333'
 }
 }
}

export default StyleStore;

Then we need to configure our app to know about our stores. We do that in the index.js file where the initial React Component gets added to the root div element.

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';

import { Provider } from 'mobx-react';
import StyleStore from './stores/StyleStore';

const stores = {
 styleStore: new StyleStore(),
}

ReactDOM.render(
 <Provider {...stores}>
 <App />
 </Provider>,
 document.getElementById('root')
);

Now we can begin to use the styleStore in our views. Lets create an ApplicationBar.js component and put it in a applicationbar folder.

import React from 'react';
import { observer, inject } from 'mobx-react';

const ApplicationBar = inject("styleStore")(observer(( { styleStore }) =>
 <div style={styleStore.applicationBarStyle}>
 <div>
 Lorem Ipsum
 </div>
 </div>
))

export default ApplicationBar

The ApplicationBar Component is a Stateless React Component. The styleStore gets injected into this components props, but we spread out the { styleStore } prop so that we can reference it directly as styleStore instead of props.styleStore.

For our example to work we need to create some buttons that uses the UI handles that we created in the StyleStore. Lets setup App.js to include the ApplicationBar component and two buttons to change between Light and Dark theme.

import React, { Component } from 'react';
import { observer } from 'mobx-react';
import ApplicationBar from './applicationbar/ApplicationBar';

@observer(["styleStore"])
class App extends Component {
 render() {
 return (
 <div>
 <ApplicationBar />
 <button onClick={()=> this.props.styleStore.switchToLightTheme()}>switchToLightTheme</button>
 <button onClick={()=> this.props.styleStore.switchToDarkTheme()}>switchToDarkTheme</button>
 </div>
 );
 }
}

export default App;

The App Component renders the ApplicationBar that uses the the StyleStore, and two buttons that each call a UI Handle on the StyleStore. When switchToDarkTheme or switchToLightTheme action is called on the styleStore, this changes the observable applicationBarStyle object and the ApplicationBar component updates.

The Proof Of Concept can the downloaded on github. Its an Ejected Create-React-App with added configs for using decorators. https://github.com/bjeld/MobxAndStyles

EDIT: I Added a post with a quick-fix to enable Decorators without ejecting