Skip to content

Instantly share code, notes, and snippets.

@amadeuszblanik
Last active January 9, 2020 16:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amadeuszblanik/e602191785a81f93e56239881dacbbba to your computer and use it in GitHub Desktop.
Save amadeuszblanik/e602191785a81f93e56239881dacbbba to your computer and use it in GitHub Desktop.
Sample use of RxJS
export { settingsStore } from "./settings";
export { withSettings } from "./withSettings";
export { useSettings } from "./useSettings";
import { BehaviorSubject } from "rxjs";
import { KIND } from "../dto";
import { Scoreboard, Settings } from "./types";
export type RESULT_SCORE = "player" | "opponent" | "draw" | "unknown";
export const initialState: Settings = {
kind: "people",
player: {
id: 0,
points: NaN,
},
opponent: {
id: 0,
points: NaN,
},
npc: {
player: true,
opponent: true,
},
result: "unknown",
totalMatches: 0,
scoreboard: {
player: 0,
opponent: 0,
},
};
const subject = new BehaviorSubject<Settings>(initialState);
export const settingsStore = {
subscription: () => subject.asObservable(),
setKind: (next: KIND) =>
subject.next({
kind: next,
player: subject.value.player,
opponent: subject.value.opponent,
npc: {
player: subject.value.npc.player,
opponent: subject.value.npc.opponent,
},
result: subject.value.result,
totalMatches: subject.value.totalMatches,
scoreboard: subject.value.scoreboard,
}),
setPlayer: (id: number, points: number) =>
subject.next({
kind: subject.value.kind,
player: {
id,
points,
},
opponent: subject.value.opponent,
npc: {
player: subject.value.npc.player,
opponent: subject.value.npc.opponent,
},
result: subject.value.result,
totalMatches: subject.value.totalMatches,
scoreboard: subject.value.scoreboard,
}),
setOpponent: (id: number, points: number) =>
subject.next({
kind: subject.value.kind,
player: subject.value.player,
opponent: {
id,
points,
},
npc: {
player: subject.value.npc.player,
opponent: subject.value.npc.opponent,
},
result: subject.value.result,
totalMatches: subject.value.totalMatches,
scoreboard: subject.value.scoreboard,
}),
setPlayerNPC: (next: boolean) =>
subject.next({
kind: subject.value.kind,
player: subject.value.player,
opponent: subject.value.opponent,
npc: {
player: next,
opponent: subject.value.npc.opponent,
},
result: subject.value.result,
totalMatches: subject.value.totalMatches,
scoreboard: subject.value.scoreboard,
}),
setOpponentNPC: (next: boolean) =>
subject.next({
kind: subject.value.kind,
player: subject.value.player,
opponent: subject.value.opponent,
npc: {
player: subject.value.npc.player,
opponent: next,
},
result: subject.value.result,
totalMatches: subject.value.totalMatches,
scoreboard: subject.value.scoreboard,
}),
setResult: (next: RESULT_SCORE) =>
subject.next({
kind: subject.value.kind,
player: subject.value.player,
opponent: subject.value.opponent,
npc: {
player: subject.value.npc.player,
opponent: subject.value.npc.opponent,
},
result: next,
totalMatches: subject.value.totalMatches,
scoreboard: subject.value.scoreboard,
}),
setTotalMatches: (next: number) =>
subject.next({
kind: subject.value.kind,
player: subject.value.player,
opponent: subject.value.opponent,
npc: {
player: subject.value.npc.player,
opponent: subject.value.npc.opponent,
},
result: subject.value.result,
totalMatches: next,
scoreboard: subject.value.scoreboard,
}),
setScoreboard: (next: Scoreboard) =>
subject.next({
kind: subject.value.kind,
player: subject.value.player,
opponent: subject.value.opponent,
npc: {
player: subject.value.npc.player,
opponent: subject.value.npc.opponent,
},
result: subject.value.result,
totalMatches: subject.value.totalMatches,
scoreboard: next,
}),
};
import { KIND } from "../dto";
import { RESULT_SCORE } from "./settings";
export interface SettingsCharacter {
id: number;
points: number;
}
export interface Scoreboard {
player: number;
opponent: number;
}
export interface Settings {
kind: KIND;
player: SettingsCharacter;
opponent: SettingsCharacter;
npc: {
player: boolean;
opponent: boolean;
};
result: RESULT_SCORE;
totalMatches: number;
scoreboard: Scoreboard;
}
import { useEffect, useState } from "react";
import { initialState, settingsStore } from "./settings";
import { Settings } from "./types";
export const useSettings = (): Settings => {
const [settings, setSettings] = useState(initialState);
const handleSubscription = (next: Settings) => {
setSettings(next);
};
useEffect(() => {
const subscription = settingsStore.subscription().subscribe(handleSubscription);
const cleanUp = () => {
subscription.unsubscribe();
};
return cleanUp;
});
return settings;
};
import React from "react";
import { Subscription } from "rxjs";
import { settingsStore } from "./settings";
import { Settings } from "./types";
export interface InjectedWithSettingsProps {
settings: Settings;
}
interface WithSettingsState {
settings: Settings;
}
export const withSettings = <P extends InjectedWithSettingsProps>(Component: React.ComponentType<P>) =>
class WithSettings extends React.PureComponent<Omit<P, keyof InjectedWithSettingsProps>, WithSettingsState> {
private settingsSubscriber: Subscription | undefined;
constructor(props: Readonly<P & InjectedWithSettingsProps>) {
super(props);
this.state = {
settings: {
kind: "people",
player: {
id: 0,
points: NaN,
},
opponent: {
id: 0,
points: NaN,
},
npc: {
player: true,
opponent: true,
},
result: "unknown",
scoreboard: {
player: 0,
opponent: 0,
},
totalMatches: 0,
},
};
}
componentDidMount() {
this.settingsSubscriber = settingsStore.subscription().subscribe(this.handleSettingsSubscriber);
}
componentWillUnmount() {
if (this.settingsSubscriber === undefined) {
return;
}
this.settingsSubscriber.unsubscribe();
}
handleSettingsSubscriber = (next: Settings) => {
this.setState({ settings: next });
};
render() {
const { ...props } = this.props;
const { settings } = this.state;
return <Component settings={settings} {...(props as P)} />;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment