From 6f275fb369651393ce8a070918222be8e02ce7d5 Mon Sep 17 00:00:00 2001 From: Lukas Boll Date: Thu, 15 Aug 2024 17:23:29 +0200 Subject: [PATCH] fix(translations): memoize array translation This commit addresses an issue where array translations were created as new objects within the core module for each render cycle, causing unnecessary rerenders. By memoizing the translation object in the material renderer set, this commit prevents redundant rerenders. This commit also adds memorization to the attributes of the material oneOfRenderer to further avoid unnecessary rerendering. closes #2342 --- .../library/layouts/array-layout.renderer.ts | 25 +++++++++++--- .../src/library/other/master-detail/master.ts | 21 ++++++++++-- .../src/library/other/table.renderer.ts | 6 ++-- packages/angular/src/library/array-control.ts | 18 ++++++++-- packages/core/src/mappers/renderer.ts | 33 ++----------------- .../MaterialListWithDetailRenderer.tsx | 12 +++++-- .../complex/MaterialArrayControlRenderer.tsx | 31 ++++++++++++----- .../src/complex/MaterialOneOfRenderer.tsx | 20 ++++++----- .../src/complex/MaterialTableControl.tsx | 3 +- .../src/layouts/MaterialArrayLayout.tsx | 7 ++-- .../layouts/MaterialArrayLayoutRenderer.tsx | 22 ++++++++++--- packages/react/src/JsonFormsContext.tsx | 20 +++++++++++ .../src/complex/TableArrayControl.tsx | 15 +++++++-- .../complex/array/ArrayControlRenderer.tsx | 13 ++++++-- 14 files changed, 169 insertions(+), 77 deletions(-) diff --git a/packages/angular-material/src/library/layouts/array-layout.renderer.ts b/packages/angular-material/src/library/layouts/array-layout.renderer.ts index 9cf7b6c9af..9f8850600f 100644 --- a/packages/angular-material/src/library/layouts/array-layout.renderer.ts +++ b/packages/angular-material/src/library/layouts/array-layout.renderer.ts @@ -33,10 +33,13 @@ import { JsonFormsAbstractControl, } from '@jsonforms/angular'; import { + arrayDefaultTranslations, ArrayLayoutProps, ArrayTranslations, createDefaultValue, + defaultJsonFormsI18nState, findUISchema, + getArrayTranslations, isObjectArrayWithNesting, JsonFormsState, mapDispatchToArrayControlProps, @@ -169,7 +172,7 @@ export class ArrayLayoutRenderer implements OnInit, OnDestroy { noData: boolean; - translations: ArrayTranslations; + translations: ArrayTranslations = {}; addItem: (path: string, value: any) => () => void; moveItemUp: (path: string, index: number) => () => void; moveItemDown: (path: string, index: number) => () => void; @@ -181,9 +184,19 @@ export class ArrayLayoutRenderer constructor(jsonFormsService: JsonFormsAngularService) { super(jsonFormsService); } - mapToProps(state: JsonFormsState): StatePropsOfArrayLayout { + mapToProps( + state: JsonFormsState + ): StatePropsOfArrayLayout & { translations: ArrayTranslations } { const props = mapStateToArrayLayoutProps(state, this.getOwnProps()); - return { ...props }; + const t = + state.jsonforms.i18n?.translate ?? defaultJsonFormsI18nState.translate; + const translations = getArrayTranslations( + t, + arrayDefaultTranslations, + props.i18nKeyPrefix, + props.label + ); + return { ...props, translations }; } remove(index: number): void { this.removeItems(this.propsPath, [index])(); @@ -211,10 +224,12 @@ export class ArrayLayoutRenderer this.moveItemDown = moveDown; this.removeItems = removeItems; } - mapAdditionalProps(props: ArrayLayoutProps) { - this.translations = props.translations; + mapAdditionalProps( + props: ArrayLayoutProps & { translations: ArrayTranslations } + ) { this.noData = !props.data || props.data === 0; this.uischemas = props.uischemas; + this.translations = props.translations; } getProps(index: number): OwnPropsOfRenderer { const uischema = findUISchema( diff --git a/packages/angular-material/src/library/other/master-detail/master.ts b/packages/angular-material/src/library/other/master-detail/master.ts index 4669f9d3f9..d50d4f092b 100644 --- a/packages/angular-material/src/library/other/master-detail/master.ts +++ b/packages/angular-material/src/library/other/master-detail/master.ts @@ -36,11 +36,14 @@ import { } from '@jsonforms/angular'; import { ArrayControlProps, + arrayDefaultTranslations, ArrayTranslations, ControlElement, createDefaultValue, decode, + defaultJsonFormsI18nState, findUISchema, + getArrayTranslations, getFirstPrimitiveProp, JsonFormsState, mapDispatchToArrayControlProps, @@ -194,7 +197,9 @@ export class MasterListComponent this.removeItems = removeItems; } - mapAdditionalProps(props: ArrayControlProps) { + mapAdditionalProps( + props: ArrayControlProps & { translations: ArrayTranslations } + ) { const { data, path, schema, uischema } = props; const controlElement = uischema as ControlElement; this.propsPath = props.path; @@ -282,9 +287,19 @@ export class MasterListComponent this.removeItems(this.propsPath, [item])(); } - protected mapToProps(state: JsonFormsState): StatePropsOfArrayControl { + protected mapToProps( + state: JsonFormsState + ): StatePropsOfArrayControl & { translations: ArrayTranslations } { const props = mapStateToArrayControlProps(state, this.getOwnProps()); - return { ...props }; + const t = + state.jsonforms.i18n?.translate ?? defaultJsonFormsI18nState.translate; + const translations = getArrayTranslations( + t, + arrayDefaultTranslations, + props.i18nKeyPrefix, + props.label + ); + return { ...props, translations }; } } diff --git a/packages/angular-material/src/library/other/table.renderer.ts b/packages/angular-material/src/library/other/table.renderer.ts index 5f38a9f6a6..3be3d7aaa5 100644 --- a/packages/angular-material/src/library/other/table.renderer.ts +++ b/packages/angular-material/src/library/other/table.renderer.ts @@ -158,7 +158,7 @@ export class TableRenderer extends JsonFormsArrayControl implements OnInit { moveItemUp: (path: string, index: number) => () => void; moveItemDown: (path: string, index: number) => () => void; removeItems: (path: string, toDelete: number[]) => () => void; - translations: ArrayTranslations; + translations: ArrayTranslations = {}; constructor(jsonformsService: JsonFormsAngularService) { super(jsonformsService); @@ -166,7 +166,9 @@ export class TableRenderer extends JsonFormsArrayControl implements OnInit { trackElement(index: number, _element: any) { return index ? index : null; } - mapAdditionalProps(props: ArrayControlProps) { + mapAdditionalProps( + props: ArrayControlProps & { translations: ArrayTranslations } + ) { this.items = this.generateCells(props.schema, props.path); this.displayedColumns = this.items.map((item) => item.property); if (this.isEnabled()) { diff --git a/packages/angular/src/library/array-control.ts b/packages/angular/src/library/array-control.ts index 013f6cd613..5e0bfbc5e5 100644 --- a/packages/angular/src/library/array-control.ts +++ b/packages/angular/src/library/array-control.ts @@ -23,6 +23,10 @@ THE SOFTWARE. */ import { + arrayDefaultTranslations, + ArrayTranslations, + defaultJsonFormsI18nState, + getArrayTranslations, JsonFormsState, mapStateToArrayControlProps, StatePropsOfArrayControl, @@ -34,8 +38,18 @@ export class JsonFormsArrayControl extends JsonFormsAbstractControl implements OnInit, OnDestroy { - protected mapToProps(state: JsonFormsState): StatePropsOfArrayControl { + protected mapToProps( + state: JsonFormsState + ): StatePropsOfArrayControl & { translations: ArrayTranslations } { const props = mapStateToArrayControlProps(state, this.getOwnProps()); - return { ...props }; + const t = + state.jsonforms.i18n?.translate ?? defaultJsonFormsI18nState.translate; + const translations = getArrayTranslations( + t, + arrayDefaultTranslations, + props.i18nKeyPrefix, + props.label + ); + return { ...props, translations }; } } diff --git a/packages/core/src/mappers/renderer.ts b/packages/core/src/mappers/renderer.ts index 60e8adfca0..fabdaa607c 100644 --- a/packages/core/src/mappers/renderer.ts +++ b/packages/core/src/mappers/renderer.ts @@ -47,13 +47,8 @@ import { getI18nKey, getI18nKeyPrefix, getI18nKeyPrefixBySchema, - getArrayTranslations, - CombinatorTranslations, - getCombinatorTranslations, - combinatorDefaultTranslations, getTranslator, getErrorTranslator, - arrayDefaultTranslations, ArrayTranslations, } from '../i18n'; import cloneDeep from 'lodash/cloneDeep'; @@ -789,7 +784,6 @@ export interface ControlWithDetailProps */ export interface StatePropsOfArrayControl extends StatePropsOfControlWithDetail { - translations: ArrayTranslations; childErrors?: ErrorObject[]; } @@ -804,12 +798,11 @@ export const mapStateToArrayControlProps = ( state: JsonFormsState, ownProps: OwnPropsOfControl ): StatePropsOfArrayControl => { - const { path, schema, uischema, i18nKeyPrefix, label, ...props } = + const { path, schema, uischema, label, ...props } = mapStateToControlWithDetailProps(state, ownProps); const resolvedSchema = Resolve.schema(schema, 'items', props.rootSchema); const childErrors = getSubErrorsAt(path, resolvedSchema)(state); - const t = getTranslator()(state); return { ...props, @@ -820,12 +813,6 @@ export const mapStateToArrayControlProps = ( childErrors, renderers: ownProps.renderers || getRenderers(state), cells: ownProps.cells || getCells(state), - translations: getArrayTranslations( - t, - arrayDefaultTranslations, - i18nKeyPrefix, - label - ), }; }; @@ -1060,7 +1047,6 @@ export interface StatePropsOfCombinator extends StatePropsOfControl { indexOfFittingSchema: number; uischemas: JsonFormsUISchemaRegistryEntry[]; data: any; - translations: CombinatorTranslations; } export const mapStateToCombinatorRendererProps = ( @@ -1072,13 +1058,6 @@ export const mapStateToCombinatorRendererProps = ( mapStateToControlProps(state, ownProps); const ajv = state.jsonforms.core.ajv; - const t = getTranslator()(state); - const translations = getCombinatorTranslations( - t, - combinatorDefaultTranslations, - i18nKeyPrefix, - label - ); const structuralKeywords = [ 'required', 'additionalProperties', @@ -1125,7 +1104,6 @@ export const mapStateToCombinatorRendererProps = ( label, indexOfFittingSchema, uischemas: getUISchemas(state), - translations, }; }; @@ -1160,7 +1138,6 @@ export const mapStateToOneOfProps = ( export interface StatePropsOfArrayLayout extends StatePropsOfControlWithDetail { data: number; - translations: ArrayTranslations; minItems?: number; disableRemove?: boolean; disableAdd?: boolean; @@ -1176,7 +1153,7 @@ export const mapStateToArrayLayoutProps = ( state: JsonFormsState, ownProps: OwnPropsOfControl ): StatePropsOfArrayLayout => { - const { path, schema, uischema, errors, i18nKeyPrefix, label, ...props } = + const { path, schema, uischema, errors, label, ...props } = mapStateToControlWithDetailProps(state, ownProps); const resolvedSchema = Resolve.schema(schema, 'items', props.rootSchema); @@ -1204,12 +1181,6 @@ export const mapStateToArrayLayoutProps = ( data: props.data ? props.data.length : 0, errors: allErrors, minItems: schema.minItems, - translations: getArrayTranslations( - t, - arrayDefaultTranslations, - i18nKeyPrefix, - label - ), }; }; diff --git a/packages/material-renderers/src/additional/MaterialListWithDetailRenderer.tsx b/packages/material-renderers/src/additional/MaterialListWithDetailRenderer.tsx index ba943d3f79..22cbc22298 100644 --- a/packages/material-renderers/src/additional/MaterialListWithDetailRenderer.tsx +++ b/packages/material-renderers/src/additional/MaterialListWithDetailRenderer.tsx @@ -25,6 +25,7 @@ import { and, ArrayLayoutProps, + ArrayTranslations, composePaths, computeLabel, createDefaultValue, @@ -36,7 +37,9 @@ import { } from '@jsonforms/core'; import { JsonFormsDispatch, + withArrayTranslationProps, withJsonFormsArrayLayoutProps, + withTranslateProps, } from '@jsonforms/react'; import { Grid, List, Typography } from '@mui/material'; import map from 'lodash/map'; @@ -63,11 +66,11 @@ export const MaterialListWithDetailRenderer = ({ cells, config, rootSchema, - translations, description, disableAdd, disableRemove, -}: ArrayLayoutProps) => { + translations, +}: ArrayLayoutProps & { translations: ArrayTranslations }) => { const [selectedIndex, setSelectedIndex] = useState(undefined); const handleRemoveItem = useCallback( (p: string, value: any) => () => { @@ -101,6 +104,7 @@ export const MaterialListWithDetailRenderer = ({ ), [uischemas, schema, uischema.scope, path, uischema, rootSchema] ); + const appliedUiSchemaOptions = merge({}, config, uischema.options); const doDisableAdd = disableAdd || appliedUiSchemaOptions.disableAdd; const doDisableRemove = disableRemove || appliedUiSchemaOptions.disableRemove; @@ -179,4 +183,6 @@ export const materialListWithDetailTester: RankedTester = rankWith( and(uiTypeIs('ListWithDetail'), isObjectArray) ); -export default withJsonFormsArrayLayoutProps(MaterialListWithDetailRenderer); +export default withJsonFormsArrayLayoutProps( + withTranslateProps(withArrayTranslationProps(MaterialListWithDetailRenderer)) +); diff --git a/packages/material-renderers/src/complex/MaterialArrayControlRenderer.tsx b/packages/material-renderers/src/complex/MaterialArrayControlRenderer.tsx index 346312b71f..8906ccbbb1 100644 --- a/packages/material-renderers/src/complex/MaterialArrayControlRenderer.tsx +++ b/packages/material-renderers/src/complex/MaterialArrayControlRenderer.tsx @@ -25,21 +25,28 @@ import React, { useCallback, useState } from 'react'; import { ArrayLayoutProps, + ArrayTranslations, RankedTester, isObjectArrayControl, isPrimitiveArrayControl, or, rankWith, } from '@jsonforms/core'; -import { withJsonFormsArrayLayoutProps } from '@jsonforms/react'; +import { + withArrayTranslationProps, + withJsonFormsArrayLayoutProps, + withTranslateProps, +} from '@jsonforms/react'; import { MaterialTableControl } from './MaterialTableControl'; import { DeleteDialog } from './DeleteDialog'; -export const MaterialArrayControlRenderer = (props: ArrayLayoutProps) => { +export const MaterialArrayControlRenderer = ( + props: ArrayLayoutProps & { translations: ArrayTranslations } +) => { const [open, setOpen] = useState(false); const [path, setPath] = useState(undefined); const [rowData, setRowData] = useState(undefined); - const { removeItems, visible } = props; + const { removeItems, visible, translations } = props; const openDeleteDialog = useCallback( (p: string, rowIndex: number) => { @@ -63,16 +70,20 @@ export const MaterialArrayControlRenderer = (props: ArrayLayoutProps) => { return ( <> - + ); @@ -83,4 +94,6 @@ export const materialArrayControlTester: RankedTester = rankWith( or(isObjectArrayControl, isPrimitiveArrayControl) ); -export default withJsonFormsArrayLayoutProps(MaterialArrayControlRenderer); +export default withJsonFormsArrayLayoutProps( + withTranslateProps(withArrayTranslationProps(MaterialArrayControlRenderer)) +); diff --git a/packages/material-renderers/src/complex/MaterialOneOfRenderer.tsx b/packages/material-renderers/src/complex/MaterialOneOfRenderer.tsx index fceca27dfe..ac6aad5230 100644 --- a/packages/material-renderers/src/complex/MaterialOneOfRenderer.tsx +++ b/packages/material-renderers/src/complex/MaterialOneOfRenderer.tsx @@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import React, { useCallback, useState } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import isEmpty from 'lodash/isEmpty'; import { TabSwitchConfirmDialog } from './TabSwitchConfirmDialog'; @@ -69,13 +69,17 @@ export const MaterialOneOfRenderer = ({ const cancel = useCallback(() => { setConfirmDialogOpen(false); }, [setConfirmDialogOpen]); - const oneOfRenderInfos = createCombinatorRenderInfos( - (schema as JsonSchema).oneOf, - rootSchema, - 'oneOf', - uischema, - path, - uischemas + const oneOfRenderInfos = useMemo( + () => + createCombinatorRenderInfos( + (schema as JsonSchema).oneOf, + rootSchema, + 'oneOf', + uischema, + path, + uischemas + ), + [schema, rootSchema, uischema, path, uischemas] ); const openNewTab = (newIndex: number) => { diff --git a/packages/material-renderers/src/complex/MaterialTableControl.tsx b/packages/material-renderers/src/complex/MaterialTableControl.tsx index e221894a88..00239fc6c0 100644 --- a/packages/material-renderers/src/complex/MaterialTableControl.tsx +++ b/packages/material-renderers/src/complex/MaterialTableControl.tsx @@ -451,7 +451,8 @@ const TableRows = ({ }; export class MaterialTableControl extends React.Component< - ArrayLayoutProps & WithDeleteDialogSupport, + ArrayLayoutProps & + WithDeleteDialogSupport & { translations: ArrayTranslations }, any > { addItem = (path: string, value: any) => this.props.addItem(path, value); diff --git a/packages/material-renderers/src/layouts/MaterialArrayLayout.tsx b/packages/material-renderers/src/layouts/MaterialArrayLayout.tsx index 6cec1d884d..6846fd421e 100644 --- a/packages/material-renderers/src/layouts/MaterialArrayLayout.tsx +++ b/packages/material-renderers/src/layouts/MaterialArrayLayout.tsx @@ -26,6 +26,7 @@ import range from 'lodash/range'; import React, { useState, useCallback } from 'react'; import { ArrayLayoutProps, + ArrayTranslations, composePaths, computeLabel, createDefaultValue, @@ -35,7 +36,9 @@ import { ArrayLayoutToolbar } from './ArrayToolbar'; import ExpandPanelRenderer from './ExpandPanelRenderer'; import merge from 'lodash/merge'; -const MaterialArrayLayoutComponent = (props: ArrayLayoutProps) => { +const MaterialArrayLayoutComponent = ( + props: ArrayLayoutProps & { translations: ArrayTranslations } +) => { const [expanded, setExpanded] = useState(false); const innerCreateDefaultValue = useCallback( () => createDefaultValue(props.schema, props.rootSchema), @@ -65,10 +68,10 @@ const MaterialArrayLayoutComponent = (props: ArrayLayoutProps) => { rootSchema, config, uischemas, - translations, description, disableAdd, disableRemove, + translations, } = props; const appliedUiSchemaOptions = merge({}, config, props.uischema.options); const doDisableAdd = disableAdd || appliedUiSchemaOptions.disableAdd; diff --git a/packages/material-renderers/src/layouts/MaterialArrayLayoutRenderer.tsx b/packages/material-renderers/src/layouts/MaterialArrayLayoutRenderer.tsx index d684301431..2fd1001e29 100644 --- a/packages/material-renderers/src/layouts/MaterialArrayLayoutRenderer.tsx +++ b/packages/material-renderers/src/layouts/MaterialArrayLayoutRenderer.tsx @@ -26,29 +26,39 @@ import React, { useCallback } from 'react'; import { ArrayLayoutProps, + ArrayTranslations, isObjectArrayWithNesting, RankedTester, rankWith, } from '@jsonforms/core'; import { MaterialArrayLayout } from './MaterialArrayLayout'; -import { withJsonFormsArrayLayoutProps } from '@jsonforms/react'; +import { + withArrayTranslationProps, + withJsonFormsArrayLayoutProps, + withTranslateProps, +} from '@jsonforms/react'; export const MaterialArrayLayoutRenderer = ({ visible, addItem, + translations, ...props -}: ArrayLayoutProps) => { +}: ArrayLayoutProps & { translations: ArrayTranslations }) => { const addItemCb = useCallback( (p: string, value: any) => addItem(p, value), [addItem] ); - if (!visible) { return null; } return ( - + ); }; @@ -56,4 +66,6 @@ export const materialArrayLayoutTester: RankedTester = rankWith( 4, isObjectArrayWithNesting ); -export default withJsonFormsArrayLayoutProps(MaterialArrayLayoutRenderer); +export default withJsonFormsArrayLayoutProps( + withTranslateProps(withArrayTranslationProps(MaterialArrayLayoutRenderer)) +); diff --git a/packages/react/src/JsonFormsContext.tsx b/packages/react/src/JsonFormsContext.tsx index 84752883a3..b10323b65f 100644 --- a/packages/react/src/JsonFormsContext.tsx +++ b/packages/react/src/JsonFormsContext.tsx @@ -78,6 +78,9 @@ import { CoreActions, Middleware, defaultMiddleware, + arrayDefaultTranslations, + getArrayTranslations, + ArrayTranslations, } from '@jsonforms/core'; import debounce from 'lodash/debounce'; import React, { @@ -889,3 +892,20 @@ export const withTranslateProps =

( return ; }; + +export const withArrayTranslationProps =

( + Component: ComponentType

+) => + function withArrayTranslatationProps(props: P & TranslateProps) { + const translations = useMemo( + () => + getArrayTranslations( + props.t, + arrayDefaultTranslations, + props.i18nKeyPrefix, + props.label + ), + [props.t, props.i18nKeyPrefix, props.label] + ); + return ; + }; diff --git a/packages/vanilla-renderers/src/complex/TableArrayControl.tsx b/packages/vanilla-renderers/src/complex/TableArrayControl.tsx index 1850b631a2..efca8f45e8 100644 --- a/packages/vanilla-renderers/src/complex/TableArrayControl.tsx +++ b/packages/vanilla-renderers/src/complex/TableArrayControl.tsx @@ -41,8 +41,14 @@ import { Test, getControlPath, encode, + ArrayTranslations, } from '@jsonforms/core'; -import { DispatchCell, withJsonFormsArrayControlProps } from '@jsonforms/react'; +import { + DispatchCell, + withArrayTranslationProps, + withJsonFormsArrayControlProps, + withTranslateProps, +} from '@jsonforms/react'; import { withVanillaControlProps } from '../util'; import type { VanillaRendererProps } from '../index'; @@ -61,7 +67,8 @@ export const tableArrayControlTester: RankedTester = rankWith( ); class TableArrayControl extends React.Component< - ArrayControlProps & VanillaRendererProps, + ArrayControlProps & + VanillaRendererProps & { translations: ArrayTranslations }, any > { confirmDelete = (path: string, index: number) => { @@ -240,5 +247,7 @@ class TableArrayControl extends React.Component< } export default withVanillaControlProps( - withJsonFormsArrayControlProps(TableArrayControl) + withJsonFormsArrayControlProps( + withTranslateProps(withArrayTranslationProps(TableArrayControl)) + ) ); diff --git a/packages/vanilla-renderers/src/complex/array/ArrayControlRenderer.tsx b/packages/vanilla-renderers/src/complex/array/ArrayControlRenderer.tsx index 884cfe586c..4c62e8ae00 100644 --- a/packages/vanilla-renderers/src/complex/array/ArrayControlRenderer.tsx +++ b/packages/vanilla-renderers/src/complex/array/ArrayControlRenderer.tsx @@ -31,10 +31,13 @@ import { findUISchema, Helpers, ControlElement, + ArrayTranslations, } from '@jsonforms/core'; import { JsonFormsDispatch, + withArrayTranslationProps, withJsonFormsArrayControlProps, + withTranslateProps, } from '@jsonforms/react'; import type { VanillaRendererProps } from '../../index'; import { withVanillaControlProps } from '../../util'; @@ -58,7 +61,8 @@ export const ArrayControl = ({ renderers, rootSchema, translations, -}: ArrayControlProps & VanillaRendererProps) => { +}: ArrayControlProps & + VanillaRendererProps & { translations: ArrayTranslations }) => { const controlElement = uischema as ControlElement; const childUiSchema = useMemo( () => @@ -184,7 +188,8 @@ export const ArrayControlRenderer = ({ enabled, errors, translations, -}: ArrayControlProps & VanillaRendererProps) => { +}: ArrayControlProps & + VanillaRendererProps & { translations: ArrayTranslations }) => { const controlElement = uischema as ControlElement; const labelDescription = Helpers.createLabelDescriptionFrom( controlElement, @@ -230,5 +235,7 @@ export const ArrayControlRenderer = ({ }; export default withVanillaControlProps( - withJsonFormsArrayControlProps(ArrayControlRenderer) + withJsonFormsArrayControlProps( + withTranslateProps(withArrayTranslationProps(ArrayControlRenderer)) + ) );