view.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * Adapted from LiteMol
  5. * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
  6. */
  7. import * as React from 'react'
  8. import { Observable, Subscription } from 'rxjs';
  9. import { merge, shallowEqual } from 'mol-util'
  10. import { Context } from '../context/context';
  11. import { Controller } from '../controller/controller';
  12. export abstract class PureView<State, Props, ViewState> extends React.Component<{
  13. state: State
  14. onChange: (s: State) => void
  15. } & Props, ViewState> {
  16. protected update(s: State) {
  17. let ns = merge<State>(this.props.state, s);
  18. if (ns !== this.props.state as any) this.props.onChange(ns);
  19. }
  20. shouldComponentUpdate(nextProps: any, nextState: any) {
  21. return !shallowEqual(this.props, nextProps) || !shallowEqual(this.state, nextState);
  22. }
  23. }
  24. export abstract class ComponentView<Props> extends React.Component<{ context: Context } & Props, {}> {
  25. // shouldComponentUpdate(nextProps: any, nextState: any) {
  26. // return !shallowEqual(this.props, nextProps);
  27. // }
  28. private subs: Subscription[] = [];
  29. protected subscribe<T>(stream: Observable<T>, obs: (n: T) => void) {
  30. let sub = stream.subscribe(obs);
  31. this.subs.push(sub);
  32. return sub;
  33. }
  34. protected unsubscribe(sub: Subscription) {
  35. let idx = this.subs.indexOf(sub);
  36. for (let i = idx; i < this.subs.length - 1; i++) {
  37. this.subs[i] = this.subs[i + 1];
  38. }
  39. sub.unsubscribe();
  40. this.subs.pop();
  41. }
  42. componentWillUnmount() {
  43. for (let s of this.subs) s.unsubscribe();
  44. this.subs = [];
  45. }
  46. }
  47. export abstract class ObserverView<P, S> extends React.Component<P, S> {
  48. private subs: Subscription[] = [];
  49. protected subscribe<T>(stream: Observable<T>, obs: (n: T) => void) {
  50. let sub = stream.subscribe(obs);
  51. this.subs.push(sub);
  52. return sub;
  53. }
  54. protected unsubscribe(sub: Subscription) {
  55. let idx = this.subs.indexOf(sub);
  56. for (let i = idx; i < this.subs.length - 1; i++) {
  57. this.subs[i] = this.subs[i + 1];
  58. }
  59. sub.unsubscribe();
  60. this.subs.pop();
  61. }
  62. componentWillUnmount() {
  63. for (let s of this.subs) s.unsubscribe();
  64. this.subs = [];
  65. }
  66. }
  67. export abstract class View<T extends Controller<any>, State, CustomProps>
  68. extends ObserverView<{ controller: T } & CustomProps, State> {
  69. public get controller(): T {
  70. return this.props.controller as any;
  71. }
  72. componentWillMount() {
  73. this.subscribe(this.controller.state as any, (s) => {
  74. this.forceUpdate()
  75. });
  76. }
  77. }