Skip to content

Commit

Permalink
prevent unnecessary re-rendering of Firehose by checking if resources…
Browse files Browse the repository at this point in the history
… are loaded when API discovery runs
  • Loading branch information
alecmerdler committed Oct 2, 2018
1 parent 2181ee3 commit 341d26f
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 30 deletions.
1 change: 0 additions & 1 deletion frontend/public/components/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ class App extends React.PureComponent {
// <LazyRoute path="/k8s/cluster/clusterroles/:name/add-rule" exact loader={() => import('./RBAC' /* webpackChunkName: "rbac" */).then(m => m.EditRulePage)} />
// <LazyRoute path="/k8s/cluster/clusterroles/:name/:rule/edit" exact loader={() => import('./RBAC' /* webpackChunkName: "rbac" */).then(m => m.EditRulePage)} />
}
<Route path="/k8s/cluster/clusterroles/:name" component={props => <ResourceDetailsPage {...props} plural="clusterroles" />} />

{
// <LazyRoute path="/k8s/ns/:ns/roles/:name/add-rule" exact loader={() => import('./RBAC' /* webpackChunkName: "rbac" */).then(m => m.EditRulePage)} />
Expand Down
14 changes: 9 additions & 5 deletions frontend/public/components/namespace.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -281,16 +281,20 @@ class NamespaceDropdown_ extends React.Component {

const NamespaceDropdown = connect(namespaceDropdownStateToProps)(NamespaceDropdown_);

const NamespaceSelector_ = ({useProjects, inFlight}) => inFlight
const NamespaceSelector_ = ({useProjects, inFlight, loaded}) => inFlight && !loaded
? <div className="co-namespace-selector" />
: <Firehose resources={[{ kind: getModel(useProjects).kind, prop: 'namespace', isList: true }]}>
<NamespaceDropdown useProjects={useProjects} />
</Firehose>;

const namespaceSelectorStateToProps = ({k8s}) => ({
inFlight: k8s.getIn(['RESOURCES', 'inFlight']),
useProjects: k8s.hasIn(['RESOURCES', 'models', ProjectModel.kind]),
});
const namespaceSelectorStateToProps = ({k8s}) => {
const useProjects = k8s.hasIn(['RESOURCES', 'models', ProjectModel.kind]);
return {
useProjects,
inFlight: k8s.getIn(['RESOURCES', 'inFlight']),
loaded: k8s.getIn([useProjects ? 'projects' : 'namespaces', 'loaded']),
};
};

export const NamespaceSelector = connect(namespaceSelectorStateToProps)(NamespaceSelector_);

Expand Down
6 changes: 4 additions & 2 deletions frontend/public/components/utils/firehose.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ const ConnectToState = connect(({k8s}, {reduxes}) => {
{inject(props.children, _.omit(props, ['children', 'className', 'reduxes']))}
</div>);

const stateToProps = ({k8s}, {resources}) => ({
const stateToProps = ({k8s}, {resources, reduxIDs = []}) => ({
k8sModels: resources.reduce((models, {kind}) => models.set(kind, k8s.getIn(['RESOURCES', 'models', kind])), ImmutableMap()),
loaded: reduxIDs.every(id => k8s.getIn([id, 'loaded'])),
inFlight: k8s.getIn(['RESOURCES', 'inFlight']),
});

Expand Down Expand Up @@ -165,7 +166,8 @@ export const Firehose = connect(
shouldComponentUpdate(nextProps, nextState, nextContext) {
const {resources: currentResources, forceUpdate = false} = this.props;

const { resources, expand, inFlight } = nextProps;
const { resources, expand, loaded } = nextProps;
const inFlight = nextProps.inFlight && !loaded;

if (_.intersectionWith(resources, currentResources, _.isEqual).length === resources.length && inFlight === this.props.inFlight) {
if (_.get(nextContext, 'router.route.location.pathname') !== _.get(this.context, 'router.route.location.pathname')) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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) => <AsyncComponent loader={() => import('../edit-yaml').then(c => c.EditYAML)} obj={props.obj} />;
export const viewYamlComponent = (props) => <AsyncComponent loader={() => import('../edit-yaml').then(c => c.EditYAML)} obj={props.obj} readOnly={true} />;

class PodsComponent extends React.PureComponent {
class PodsComponent extends React.PureComponent<PodsComponentProps> {
render() {
const {metadata: {namespace}, spec: {selector}} = this.props.obj;
if (_.isEmpty(selector)) {
Expand All @@ -25,7 +28,14 @@ class PodsComponent extends React.PureComponent {
}
}

export const navFactory = {
type Page = {
href: string;
name: string;
component?: React.ComponentType<any>;
};

type NavFactory = {[name: string]: (c?: React.ComponentType<any>) => Page};
export const navFactory: NavFactory = {
details: component => ({
href: '',
name: 'Overview',
Expand Down Expand Up @@ -78,8 +88,7 @@ export const navFactory = {
})
};

/** @type {React.SFC<{pages: {href: string, name: string}[], basePath: string}>} */
export const NavBar = ({pages, basePath}) => {
export const NavBar: React.SFC<NavBarProps> = ({pages, basePath}) => {
const divider = <li className="co-m-horizontal-nav__menu-item co-m-horizontal-nav__menu-item--divider" key="_divider" />;
basePath = basePath.replace(/\/$/, '');

Expand All @@ -94,14 +103,25 @@ 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<HorizontalNavProps> {
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']), obj: props.obj.data};
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}`;
Expand All @@ -122,15 +142,22 @@ 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,
}),
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<any>;
};
2 changes: 1 addition & 1 deletion frontend/public/components/utils/resource-link.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const resourceObjPath = (obj, kind) => resourcePath(kind, _.get(obj, 'met

export const ResourceLink = connectToModel(
({className, kind, name, namespace, title, displayName, linkTo = true, kindsInFlight}) => {
if (kindsInFlight) {
if (!kind && kindsInFlight) {
return null;
}
const path = resourcePath(kind, name, namespace);
Expand Down
2 changes: 1 addition & 1 deletion frontend/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 341d26f

Please sign in to comment.