improve perf of instance select dropdown

This commit is contained in:
Tao Bojlen 2018-08-29 03:52:21 +02:00
parent 74511c67dd
commit 0f2aa3c938
8 changed files with 37 additions and 35 deletions

View file

@ -1,10 +0,0 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { App } from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});

View file

@ -10,7 +10,7 @@ import { fetchInstances } from './redux/actions';
import { IAppState, IInstance } from './redux/types';
interface IAppProps {
currentInstance: IInstance | null;
currentInstanceName?: string | null;
instances?: IInstance[],
isLoadingInstances: boolean,
fetchInstances: () => void;
@ -61,7 +61,7 @@ class AppImpl extends React.Component<IAppProps> {
className="fediverse-welcome"
icon={IconNames.SEARCH_AROUND}
title="Graph. TODO"
description={"Selected " + ((this.props.currentInstance && this.props.currentInstance.name) || "nothing")}
description={"Selected " + (this.props.currentInstanceName || "nothing")}
/>
</div>
);
@ -70,7 +70,7 @@ class AppImpl extends React.Component<IAppProps> {
}
const mapStateToProps = (state: IAppState) => ({
currentInstance: state.currentInstance,
currentInstanceName: state.currentInstanceName,
instances: state.data.instances,
isLoadingInstances: state.data.isLoadingInstances,
})

View file

@ -1,17 +1,16 @@
import * as React from 'react';
import { connect } from 'react-redux';
// import { List, ListRowProps } from 'react-virtualized';
import { Dispatch } from 'redux';
import { Button, MenuItem } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import { ItemPredicate, ItemRenderer, Select } from '@blueprintjs/select';
import { IItemRendererProps, ItemPredicate, Select } from '@blueprintjs/select';
import { selectInstance } from '../redux/actions';
import { IAppState, IInstance } from '../redux/types';
interface IInstanceSearchProps {
currentInstance: IInstance | null;
currentInstanceName: string | null;
instances?: IInstance[];
selectInstance: (instanceName: string) => void;
}
@ -28,33 +27,48 @@ class InstanceSearchImpl extends React.Component<IInstanceSearchProps> {
onItemSelect={this.onItemSelect}
itemPredicate={this.itemPredicate}
disabled={!this.props.instances}
initialContent={this.renderInitialContent()}
noResults={this.renderNoResults()}
popoverProps={{popoverClassName: "fediverse-instance-search-popover"}}
>
<Button
icon={IconNames.SELECTION}
rightIcon={IconNames.CARET_DOWN}
text={(this.props.currentInstance && this.props.currentInstance.name) || ("Select an instance")}
text={this.props.currentInstanceName || ("Select an instance")}
disabled={!this.props.instances}
/>
</InstanceSelect>
);
}
private itemRenderer: ItemRenderer<IInstance> = (item, { handleClick, modifiers }) => {
if (!modifiers.matchesPredicate) {
private renderInitialContent = () => {
return (
<MenuItem disabled={true} text={"Start typing"} />
);
}
private renderNoResults = () => {
return (
<MenuItem disabled={true} text={"Keep typing"} />
);
}
private itemRenderer = (item: IInstance, itemProps: IItemRendererProps) => {
if (!itemProps.modifiers.matchesPredicate) {
return null;
}
return (
<MenuItem
text={item.name}
key={item.name}
active={modifiers.active}
onClick={handleClick}
active={itemProps.modifiers.active}
onClick={itemProps.handleClick}
/>
);
}
private itemPredicate: ItemPredicate<IInstance> = (query, item, index) => {
if (!item.name) {
if (!item.name || query.length < 4) {
return false;
}
return item.name.toLowerCase().indexOf(query.toLowerCase()) >= 0;
@ -66,7 +80,7 @@ class InstanceSearchImpl extends React.Component<IInstanceSearchProps> {
}
const mapStateToProps = (state: IAppState) => ({
currentInstance: state.currentInstance,
currentInstanceName: state.currentInstanceName,
instances: state.data.instances,
})
const mapDispatchToProps = (dispatch: Dispatch) => ({

View file

@ -12,7 +12,7 @@ html, body {
}
.fediverse-instance-search-popover {
height: 350px;
min-width: 214px;
max-height: 350px;
min-width: 300px;
overflow-x: hidden;
}

View file

@ -3,11 +3,9 @@ import { Dispatch } from 'redux';
import { getFromApi } from '../util';
import { ActionType, IInstance } from './types';
export const selectInstance = (instance: string) => {
export const selectInstance = (instanceName: string) => {
return {
payload: {
instance,
},
payload: instanceName,
type: ActionType.SELECT_INSTANCE,
}
}

View file

@ -1,6 +1,6 @@
import { combineReducers } from 'redux';
import { ActionType, IAction, IDataState, IInstance } from './types';
import { ActionType, IAction, IDataState } from './types';
const initialDataState = {
isLoadingInstances: false,
@ -24,7 +24,7 @@ const data = (state: IDataState = initialDataState, action: IAction) => {
}
}
const currentInstance = (state: IInstance | null = null, action: IAction): IInstance | null => {
const currentInstanceName = (state: string | null = null, action: IAction): string | null => {
switch (action.type) {
case ActionType.SELECT_INSTANCE:
return action.payload;
@ -34,6 +34,6 @@ const currentInstance = (state: IInstance | null = null, action: IAction): IInst
}
export const rootReducer = combineReducers({
currentInstance,
currentInstanceName,
data,
})

View file

@ -20,6 +20,6 @@ export interface IDataState {
}
export interface IAppState {
currentInstance: IInstance | null,
currentInstanceName: string | null,
data: IDataState,
}

View file

@ -1,7 +1,7 @@
import fetch from 'cross-fetch';
// const API_ROOT = "https://fediverse.space/api/v1/"
const API_ROOT = "http://localhost:8000/api/v1/"
const API_ROOT = "https://fediverse.space/api/v1/"
// const API_ROOT = "http://localhost:8000/api/v1/"
export const getFromApi = (path: string): Promise<any> => {
const domain = API_ROOT.endsWith("/") ? API_ROOT : API_ROOT + "/";