chore: refactor ObjectSchema and Field, less rerenders on expand

This commit is contained in:
Roman Hotsiy 2018-02-08 11:40:43 +02:00
parent 1f7fc44292
commit 71e189ffc5
No known key found for this signature in database
GPG Key ID: 5CB7B3ACABA57CB0
3 changed files with 66 additions and 66 deletions

View File

@ -7,15 +7,17 @@ import {
PropertyBullet, PropertyBullet,
PropertyDetailsCell, PropertyDetailsCell,
PropertyNameCell, PropertyNameCell,
InnerPropertiesWrap,
PropertyCellWithInner,
} from '../../common-elements/fields-layout'; } from '../../common-elements/fields-layout';
import { ShelfIcon } from '../../common-elements/'; import { ShelfIcon } from '../../common-elements/';
import { FieldModel } from '../../services/models'; import { FieldModel } from '../../services/models';
import { Schema, SchemaOptions } from '../Schema/Schema';
export interface FieldProps { export interface FieldProps extends SchemaOptions {
className?: string; className?: string;
onClick?: () => void;
isLast?: boolean; isLast?: boolean;
showExamples?: boolean; showExamples?: boolean;
@ -25,15 +27,16 @@ export interface FieldProps {
} }
export class Field extends React.PureComponent<FieldProps> { export class Field extends React.PureComponent<FieldProps> {
toggle = () => {
this.props.field.toggle();
};
render() { render() {
const { className, field, isLast } = this.props; const { className, field, isLast } = this.props;
const { name, expanded, deprecated, required } = field; const { name, expanded, deprecated, required } = field;
const withSubSchema = !field.schema.isPrimitive && !field.schema.isCircular;
const paramName = this.props.onClick ? ( const paramName = withSubSchema ? (
<ClickablePropertyNameCell <ClickablePropertyNameCell onClick={this.toggle} className={deprecated ? 'deprecated' : ''}>
onClick={this.props.onClick}
className={deprecated ? 'deprecated' : ''}
>
<PropertyBullet /> <PropertyBullet />
{name} {name}
<ShelfIcon size={'1.2em'} direction={expanded ? 'down' : 'right'} /> <ShelfIcon size={'1.2em'} direction={expanded ? 'down' : 'right'} />
@ -47,12 +50,29 @@ export class Field extends React.PureComponent<FieldProps> {
</PropertyNameCell> </PropertyNameCell>
); );
return ( return (
<>
<tr className={isLast ? 'last ' + className : className}> <tr className={isLast ? 'last ' + className : className}>
{paramName} {paramName}
<PropertyDetailsCell> <PropertyDetailsCell>
<FieldDetails {...this.props} /> <FieldDetails {...this.props} />
</PropertyDetailsCell> </PropertyDetailsCell>
</tr> </tr>
{field.expanded &&
withSubSchema && (
<tr key={field.name + 'inner'}>
<PropertyCellWithInner colSpan={2}>
<InnerPropertiesWrap>
<Schema
schema={field.schema}
skipReadOnly={this.props.skipReadOnly}
skipWriteOnly={this.props.skipWriteOnly}
showTitle={this.props.showTitle}
/>
</InnerPropertiesWrap>
</PropertyCellWithInner>
</tr>
)}
</>
); );
} }
} }

View File

@ -1,17 +1,12 @@
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import * as React from 'react'; import * as React from 'react';
import { FieldModel, SchemaModel } from '../../services/models'; import { SchemaModel } from '../../services/models';
import { import { PropertiesTable, PropertiesTableCaption } from '../../common-elements/fields-layout';
InnerPropertiesWrap,
PropertiesTable,
PropertiesTableCaption,
PropertyCellWithInner,
} from '../../common-elements/fields-layout';
import { Field } from '../Fields/Field'; import { Field } from '../Fields/Field';
import { DiscriminatorDropdown } from './DiscriminatorDropdown'; import { DiscriminatorDropdown } from './DiscriminatorDropdown';
import { Schema, SchemaProps } from './Schema'; import { SchemaProps } from './Schema';
import { mapWithLast } from '../../utils'; import { mapWithLast } from '../../utils';
@ -28,42 +23,6 @@ export class ObjectSchema extends React.Component<ObjectSchemaProps> {
return this.props.discriminator!.parentSchema; return this.props.discriminator!.parentSchema;
} }
renderField(field: FieldModel, isLast: boolean, isDiscriminator: boolean = false) {
const withSubSchema = !field.schema.isPrimitive && !field.schema.isCircular;
return [
<Field
key={field.name}
isLast={isLast}
field={field}
onClick={(withSubSchema && (() => field.toggle())) || undefined}
renderDiscriminatorSwitch={
(isDiscriminator &&
(() => (
<DiscriminatorDropdown parent={this.parentSchema} enumValues={field.schema.enum} />
))) ||
undefined
}
className={field.expanded ? 'expanded' : undefined}
showExamples={false}
/>,
field.expanded &&
withSubSchema && (
<tr key={field.name + 'inner'}>
<PropertyCellWithInner colSpan={2}>
<InnerPropertiesWrap>
<Schema
schema={field.schema}
skipReadOnly={this.props.skipReadOnly}
skipWriteOnly={this.props.skipWriteOnly}
showTitle={this.props.showTitle}
/>
</InnerPropertiesWrap>
</PropertyCellWithInner>
</tr>
),
];
}
render() { render() {
const { schema: { fields = [] }, showTitle, discriminator } = this.props; const { schema: { fields = [] }, showTitle, discriminator } = this.props;
@ -82,13 +41,31 @@ export class ObjectSchema extends React.Component<ObjectSchemaProps> {
<PropertiesTable> <PropertiesTable>
{showTitle && <PropertiesTableCaption>{this.props.schema.title}</PropertiesTableCaption>} {showTitle && <PropertiesTableCaption>{this.props.schema.title}</PropertiesTableCaption>}
<tbody> <tbody>
{mapWithLast(filteredFields, (field, isLast) => {mapWithLast(filteredFields, (field, isLast) => {
this.renderField( return (
field, <Field
isLast, key={field.name}
discriminator && discriminator.fieldName === field.name, isLast={isLast}
), field={field}
)} renderDiscriminatorSwitch={
(discriminator &&
discriminator.fieldName === field.name &&
(() => (
<DiscriminatorDropdown
parent={this.parentSchema}
enumValues={field.schema.enum}
/>
))) ||
undefined
}
className={field.expanded ? 'expanded' : undefined}
showExamples={false}
skipReadOnly={this.props.skipReadOnly}
skipWriteOnly={this.props.skipWriteOnly}
showTitle={this.props.showTitle}
/>
);
})}
</tbody> </tbody>
</PropertiesTable> </PropertiesTable>
); );

View File

@ -10,13 +10,16 @@ import { ArraySchema } from './ArraySchema';
import { ObjectSchema } from './ObjectSchema'; import { ObjectSchema } from './ObjectSchema';
import { OneOfSchema } from './OneOfSchema'; import { OneOfSchema } from './OneOfSchema';
export interface SchemaProps { export interface SchemaOptions {
schema: SchemaModel;
showTitle?: boolean; showTitle?: boolean;
skipReadOnly?: boolean; skipReadOnly?: boolean;
skipWriteOnly?: boolean; skipWriteOnly?: boolean;
} }
export interface SchemaProps extends SchemaOptions {
schema: SchemaModel;
}
@observer @observer
export class Schema extends React.Component<Partial<SchemaProps>> { export class Schema extends React.Component<Partial<SchemaProps>> {
render() { render() {