Turbo Render (#298)

* More responsive React updates on scroll

* `Icon`s now use shadow dom

* Faster Sparkline

* Recycle table rows

* Separate Header from Chain to avoid vdom diffing

* Separate THead from Row.HEADER to avoid vdom diffing

* Throttle rendering updates on chain tabs, also styles

* Minor tweaks and fixes

* Created components for all columns

* Wrapping up Column refactor

* Rename Row--td to Column

* Lazy `Ago`

* Update styles for faster layouting

* Minor cleanup

* Fix Connection

* Use shadow DOM in `PolkadotIcon`

* Comments and tweaks for the List component

* Faster Tooltip and Truncate

* Minor tweaks

* Tooltiped columns can now be copied

* Future-proof Connection

* Remove the <div> wrapper from Icon

* Fix dash on missing graph data

* Clean up some SVGs

* Cleanup and comments

* Localize the use of `previousKeys` to `recalculateKeys`

* Custom appState disjoint from React component state

* Make appState and appUpdate refs readonly

* Cleanup
This commit is contained in:
Maciej Hirsz
2020-11-11 13:41:01 +01:00
committed by GitHub
parent 675776c3e1
commit ebb01c1a7d
72 changed files with 1863 additions and 1118 deletions
+27 -22
View File
@@ -1,3 +1,4 @@
import * as React from 'react';
import { Types, Maybe, SortedCollection } from './common';
import { Column } from './components/List';
@@ -69,7 +70,7 @@ export class Node {
public lon: Maybe<Types.Longitude>;
public city: Maybe<Types.City>;
private readonly subscriptions = new Set<(node: Node) => void>();
private _changeRef = 0;
private readonly subscriptionsConsensus = new Set<(node: Node) => void>();
constructor(
@@ -188,29 +189,36 @@ export class Node {
}
}
public subscribe(handler: (node: Node) => void) {
this.subscriptions.add(handler);
}
public unsubscribe(handler: (node: Node) => void) {
this.subscriptions.delete(handler);
}
public subscribeConsensus(handler: (node: Node) => void) {
this.subscriptionsConsensus.add(handler);
}
public unsubscribeConsensus(handler: (node: Node) => void) {
this.subscriptionsConsensus.delete(handler);
public get changeRef(): number {
return this._changeRef;
}
private trigger() {
for (const handler of this.subscriptions.values()) {
handler(this);
}
this._changeRef += 1;
}
}
export function bindState(bind: React.Component, state: State): Update {
let isUpdating = false;
return (changes) => {
// Apply new changes to the state immediately
Object.assign(state, changes);
// Trigger React update on next animation frame only once
if (!isUpdating) {
isUpdating = true;
window.requestAnimationFrame(() => {
bind.forceUpdate();
isUpdating = false;
});
}
return state;
};
}
export namespace State {
export interface Settings {
location: boolean;
@@ -262,11 +270,8 @@ export interface State {
}
export type Update = <K extends keyof State>(
changes: Pick<State, K> | null
changes: Pick<State, K>
) => Readonly<State>;
export type UpdateBound = <K extends keyof State>(
changes: Pick<State, K> | null
) => void;
export interface ChainData {
label: Types.ChainLabel;