From 993bd2ddb95245c6f8c7c4ebb816c95e97550024 Mon Sep 17 00:00:00 2001 From: alecmerdler Date: Fri, 28 Sep 2018 16:04:57 -0400 Subject: [PATCH] prevent unnecessary re-rendering of Firehose by checking if resources are loaded when API discovery runs --- .../public/components/factory/details.tsx | 2 + frontend/public/components/utils/firehose.jsx | 4 +- ...{horizontal-nav.jsx => horizontal-nav.tsx} | 68 +++++++++++++------ frontend/tsconfig.json | 2 +- 4 files changed, 53 insertions(+), 23 deletions(-) rename frontend/public/components/utils/{horizontal-nav.jsx => horizontal-nav.tsx} (70%) diff --git a/frontend/public/components/factory/details.tsx b/frontend/public/components/factory/details.tsx index fc7a065f70d1..420b11e87e7b 100644 --- a/frontend/public/components/factory/details.tsx +++ b/frontend/public/components/factory/details.tsx @@ -31,6 +31,8 @@ export const DetailsPage: React.SFC = (props) => { {inject(props.children, _.omit(props, ['children', 'className', 'reduxes']))} ); -const stateToProps = ({k8s}, {resources}) => ({ +const stateToProps = ({k8s}, {resources, reduxIDs = []}) => ({ k8sModels: resources.reduce((models, {kind}) => models.set(kind, k8s.getIn(['RESOURCES', 'models', kind])), ImmutableMap()), - inFlight: k8s.getIn(['RESOURCES', 'inFlight']), + inFlight: k8s.getIn(['RESOURCES', 'inFlight']) && reduxIDs.some(id => !k8s.getIn([id, 'loaded'])), }); export const Firehose = connect( diff --git a/frontend/public/components/utils/horizontal-nav.jsx b/frontend/public/components/utils/horizontal-nav.tsx similarity index 70% rename from frontend/public/components/utils/horizontal-nav.jsx rename to frontend/public/components/utils/horizontal-nav.tsx index a57c69fe1c67..8d3d7f742384 100644 --- a/frontend/public/components/utils/horizontal-nav.jsx +++ b/frontend/public/components/utils/horizontal-nav.tsx @@ -1,3 +1,5 @@ +/* eslint-disable no-undef, no-unused-vars */ + import * as _ from 'lodash-es'; import * as React from 'react'; import * as classNames from 'classnames'; @@ -7,11 +9,12 @@ import { Route, Switch, Link } from 'react-router-dom'; import { EmptyBox, StatusBox } from '.'; import { PodsPage } from '../pod'; import { AsyncComponent } from './async'; +import { K8sResourceKind } from '../../module/k8s'; const editYamlComponent = (props) => import('../edit-yaml').then(c => c.EditYAML)} obj={props.obj} />; export const viewYamlComponent = (props) => import('../edit-yaml').then(c => c.EditYAML)} obj={props.obj} readOnly={true} />; -class PodsComponent extends React.PureComponent { +class PodsComponent extends React.PureComponent { render() { const {metadata: {namespace}, spec: {selector}} = this.props.obj; if (_.isEmpty(selector)) { @@ -25,7 +28,8 @@ class PodsComponent extends React.PureComponent { } } -export const navFactory = { +type NavFactory = {[name: string]: (c?: React.ComponentType) => Page}; +export const navFactory: NavFactory = { details: component => ({ href: '', name: 'Overview', @@ -78,8 +82,7 @@ export const navFactory = { }) }; -/** @type {React.SFC<{pages: {href: string, name: string}[], basePath: string}>} */ -export const NavBar = ({pages, basePath}) => { +export const NavBar: React.SFC = ({pages, basePath}) => { const divider =
  • ; basePath = basePath.replace(/\/$/, ''); @@ -94,14 +97,26 @@ export const NavBar = ({pages, basePath}) => { }; NavBar.displayName = 'NavBar'; -/** @augments {React.PureComponent<{className?: string, label?: string, pages: {href: string, name: string, component: React.ComponentType}[], match: any, resourceKeys?: string[]}>} */ -export class HorizontalNav extends React.PureComponent { +export class HorizontalNav extends React.PureComponent { + static propTypes = { + pages: PropTypes.arrayOf(PropTypes.shape({ + href: PropTypes.string, + name: PropTypes.string, + component: PropTypes.func, + })), + className: PropTypes.string, + hideNav: PropTypes.bool, + match: PropTypes.shape({ + path: PropTypes.string, + }), + }; + render () { const props = this.props; - const componentProps = _.pick(props, ['filters', 'selected', 'match']); - componentProps.obj = props.obj.data; - const extraResources = _.reduce(props.resourceKeys, (acc, key) => ({...acc, [key]: props[key].data}), {}); + const componentProps = {..._.pick(props, ['filters', 'selected', 'match']), data: props.obj.data}; + // FIXME(alecmerdler): `props.obj === undefined` + const extraResources = _.reduce(props.resourceKeys, (extraObjs, key) => ({...extraObjs, [key]: props[key].data}), {}); const routes = props.pages.map(p => { const path = `${props.match.url}/${p.href}`; @@ -122,15 +137,28 @@ export class HorizontalNav extends React.PureComponent { } } -HorizontalNav.propTypes = { - pages: PropTypes.arrayOf(PropTypes.shape({ - href: PropTypes.string, - name: PropTypes.string, - component: PropTypes.func, - })), - className: PropTypes.string, - hideNav: PropTypes.bool, - match: PropTypes.shape({ - path: PropTypes.string, - }), +type Page = { + href: string; + name: string; + component?: React.ComponentType; +}; + +export type PodsComponentProps = { + obj: K8sResourceKind; +}; + +export type NavBarProps = { + pages: Page[]; + basePath: string; +}; + +export type HorizontalNavProps = { + className?: string; + obj: {loaded: boolean, data: K8sResourceKind}; + label?: string; + pages: Page[]; + match: any; + resourceKeys?: string[]; + hideNav?: boolean; + EmptyMsg?: React.ComponentType; }; diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 75ea14fa5e36..072cbf2ab952 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -5,7 +5,7 @@ "moduleResolution": "node", "outDir": "./public/dist/build/", "target": "es5", - "lib": ["dom", "es2015"], + "lib": ["dom", "es2015", "es2016.array.include"], "jsx": "react", "allowJs": true, "downlevelIteration": true,