Migrate SnackStore to mobx

This commit is contained in:
Jannis Mattheis 2018-10-21 12:36:16 +02:00
parent 8947dbb9bd
commit 9fe00bf004
3 changed files with 55 additions and 62 deletions

View File

@ -2,44 +2,37 @@ import IconButton from '@material-ui/core/IconButton';
import Snackbar from '@material-ui/core/Snackbar';
import Close from '@material-ui/icons/Close';
import React, {Component} from 'react';
import SnackBarStore from '../stores/SnackBarStore';
import {observable, reaction} from 'mobx';
import {observer} from 'mobx-react';
import SnackManager from '../stores/SnackManager';
interface IState {
current: string;
hasNext: boolean;
open: boolean;
openWhen: number;
}
class SnackBarHandler extends Component<{}, IState> {
@observer
class SnackBarHandler extends Component {
private static MAX_VISIBLE_SNACK_TIME_IN_MS = 6000;
private static MIN_VISIBLE_SNACK_TIME_IN_MS = 1000;
public state = {
current: '',
hasNext: false,
open: false,
openWhen: 0,
};
@observable
private open = false;
@observable
private openWhen = 0;
public componentWillMount() {
SnackBarStore.on('change', this.onNewSnack);
}
private dispose: () => void = () => {};
public componentWillUnmount() {
SnackBarStore.removeListener('change', this.onNewSnack);
}
public componentDidMount = () =>
(this.dispose = reaction(() => SnackManager.counter, this.onNewSnack));
public componentWillUnmount = () => this.dispose();
public render() {
const {open, current, hasNext} = this.state;
const duration = hasNext
const {message: current, hasNext} = SnackManager;
const duration = hasNext()
? SnackBarHandler.MIN_VISIBLE_SNACK_TIME_IN_MS
: SnackBarHandler.MAX_VISIBLE_SNACK_TIME_IN_MS;
return (
<Snackbar
anchorOrigin={{vertical: 'bottom', horizontal: 'left'}}
open={open}
open={this.open}
autoHideDuration={duration}
onClose={this.closeCurrentSnack}
onExited={this.openNextSnack}
@ -58,7 +51,7 @@ class SnackBarHandler extends Component<{}, IState> {
}
private onNewSnack = () => {
const {open, openWhen} = this.state;
const {open, openWhen} = this;
if (!open) {
this.openNextSnack();
@ -77,18 +70,14 @@ class SnackBarHandler extends Component<{}, IState> {
};
private openNextSnack = () => {
if (SnackBarStore.hasNext()) {
this.setState({
...this.state,
open: true,
openWhen: Date.now(),
current: SnackBarStore.next(),
hasNext: SnackBarStore.hasNext(),
});
if (SnackManager.hasNext()) {
this.open = true;
this.openWhen = Date.now();
SnackManager.next();
}
};
private closeCurrentSnack = () => this.setState({...this.state, open: false});
private closeCurrentSnack = () => (this.open = false);
}
export default SnackBarHandler;

View File

@ -1,28 +0,0 @@
import {EventEmitter} from 'events';
import dispatcher, {IEvent} from './dispatcher';
class SnackBarStore extends EventEmitter {
public messages: string[] = [];
public next(): string {
if (!this.hasNext()) {
throw new Error('no such element');
}
return this.messages.shift() as string;
}
public hasNext(): boolean {
return this.messages.length !== 0;
}
public handle(data: IEvent): void {
if (data.type === 'SNACK') {
this.messages.push(data.payload);
this.emit('change');
}
}
}
const store = new SnackBarStore();
dispatcher.register(store.handle.bind(store));
export default store;

View File

@ -0,0 +1,32 @@
import {action, observable} from 'mobx';
export interface SnackReporter {
(message: string): void;
}
class SnackManager {
@observable
private messages: string[] = [];
@observable
public message: string | null;
@observable
public counter = 0;
@action
public next = (): void => {
if (!this.hasNext()) {
throw new Error('There is nothing here :(');
}
this.message = this.messages.shift() as string;
};
public hasNext = () => this.messages.length > 0;
@action
public snack: SnackReporter = (message: string): void => {
this.messages.push(message);
this.counter++;
};
}
export default new SnackManager();