Send widget to error boundary for too many renders (#2541)

* Send widget to error boundary for too many renders

* Reset renderStartTime once check for too many renders are completed
This commit is contained in:
Sherfin Shamsudeen 2022-03-16 18:12:20 +05:30 committed by GitHub
parent 5ec645a845
commit a1eaaad33c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 110 additions and 90 deletions

View file

@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import { Button } from './Components/Button';
import { Image } from './Components/Image';
import { Text } from './Components/Text';
@ -120,10 +120,27 @@ export const Box = function Box({
}
const ComponentToRender = AllComponents[component.component];
const [renderCount, setRenderCount] = useState(0);
const [renderStartTime, setRenderStartTime] = useState(new Date());
const resolvedProperties = resolveProperties(component, currentState, null, customResolvables);
const resolvedStyles = resolveStyles(component, currentState, null, customResolvables);
resolvedStyles.visibility = resolvedStyles.visibility !== false ? true : false;
useEffect(() => {
setRenderCount(renderCount + 1);
if (renderCount > 10) {
setRenderCount(0);
const currentTime = new Date();
const timeDifference = Math.abs(currentTime - renderStartTime);
if (timeDifference < 1000) {
throw Error;
}
setRenderStartTime(currentTime);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [JSON.stringify({ resolvedProperties, resolvedStyles })]);
let exposedVariables = {};
let isListView = false;
@ -165,58 +182,56 @@ export const Box = function Box({
trigger={!inCanvas ? ['hover', 'focus'] : null}
overlay={(props) => renderTooltip({ props, text: `${component.description}` })}
>
<ErrorBoundary showFallback={mode === 'edit'}>
<div style={{ ...styles, backgroundColor }} role={preview ? 'BoxPreview' : 'Box'}>
{inCanvas ? (
<ComponentToRender
onComponentClick={onComponentClick}
onComponentOptionChanged={onComponentOptionChanged}
currentState={currentState}
onEvent={onEvent}
id={id}
paramUpdated={paramUpdated}
width={width}
changeCanDrag={changeCanDrag}
onComponentOptionsChanged={onComponentOptionsChanged}
height={height}
component={component}
containerProps={containerProps}
darkMode={darkMode}
removeComponent={removeComponent}
canvasWidth={canvasWidth}
properties={resolvedProperties}
exposedVariables={exposedVariables}
styles={resolvedStyles}
setExposedVariable={(variable, value) => onComponentOptionChanged(component, variable, value, extraProps)}
registerAction={(actionName, func) => onComponentOptionChanged(component, actionName, func)}
fireEvent={fireEvent}
validate={validate}
parentId={parentId}
customResolvables={customResolvables}
></ComponentToRender>
) : (
<div className="m-1" style={{ height: '76px', width: '76px', marginLeft: '18px' }}>
<div
className="component-image-holder p-2 d-flex flex-column justify-content-center"
style={{ height: '100%' }}
>
<center>
<div
style={{
width: '20px',
height: '20px',
backgroundSize: 'contain',
backgroundImage: `url(/assets/images/icons/widgets/${component.name.toLowerCase()}.svg)`,
backgroundRepeat: 'no-repeat',
}}
></div>
</center>
<span className="component-title">{component.displayName}</span>
</div>
<div style={{ ...styles, backgroundColor }} role={preview ? 'BoxPreview' : 'Box'}>
{inCanvas ? (
<ComponentToRender
onComponentClick={onComponentClick}
onComponentOptionChanged={onComponentOptionChanged}
currentState={currentState}
onEvent={onEvent}
id={id}
paramUpdated={paramUpdated}
width={width}
changeCanDrag={changeCanDrag}
onComponentOptionsChanged={onComponentOptionsChanged}
height={height}
component={component}
containerProps={containerProps}
darkMode={darkMode}
removeComponent={removeComponent}
canvasWidth={canvasWidth}
properties={resolvedProperties}
exposedVariables={exposedVariables}
styles={resolvedStyles}
setExposedVariable={(variable, value) => onComponentOptionChanged(component, variable, value, extraProps)}
registerAction={(actionName, func) => onComponentOptionChanged(component, actionName, func)}
fireEvent={fireEvent}
validate={validate}
parentId={parentId}
customResolvables={customResolvables}
></ComponentToRender>
) : (
<div className="m-1" style={{ height: '76px', width: '76px', marginLeft: '18px' }}>
<div
className="component-image-holder p-2 d-flex flex-column justify-content-center"
style={{ height: '100%' }}
>
<center>
<div
style={{
width: '20px',
height: '20px',
backgroundSize: 'contain',
backgroundImage: `url(/assets/images/icons/widgets/${component.name.toLowerCase()}.svg)`,
backgroundRepeat: 'no-repeat',
}}
></div>
</center>
<span className="component-title">{component.displayName}</span>
</div>
)}
</div>
</ErrorBoundary>
</div>
)}
</div>
</OverlayTrigger>
);
};

View file

@ -7,6 +7,7 @@ import { getEmptyImage } from 'react-dnd-html5-backend';
import { Box } from './Box';
import { ConfigHandle } from './ConfigHandle';
import { Rnd } from 'react-rnd';
import ErrorBoundary from './ErrorBoundary';
const resizerClasses = {
topRight: 'top-right',
@ -250,49 +251,53 @@ export const DraggableBox = function DraggableBox({
setSelectedComponent={(id, component) => setSelectedComponent(id, component)}
/>
)}
<Box
component={component}
id={id}
width={width}
height={currentLayoutOptions.height - 4}
mode={mode}
changeCanDrag={changeCanDrag}
inCanvas={inCanvas}
paramUpdated={paramUpdated}
onEvent={onEvent}
onComponentOptionChanged={onComponentOptionChanged}
onComponentOptionsChanged={onComponentOptionsChanged}
onComponentClick={onComponentClick}
currentState={currentState}
containerProps={containerProps}
darkMode={darkMode}
removeComponent={removeComponent}
canvasWidth={canvasWidth}
readOnly={readOnly}
customResolvables={customResolvables}
parentId={parentId}
allComponents={allComponents}
extraProps={extraProps}
/>
<ErrorBoundary showFallback={mode === 'edit'}>
<Box
component={component}
id={id}
width={width}
height={currentLayoutOptions.height - 4}
mode={mode}
changeCanDrag={changeCanDrag}
inCanvas={inCanvas}
paramUpdated={paramUpdated}
onEvent={onEvent}
onComponentOptionChanged={onComponentOptionChanged}
onComponentOptionsChanged={onComponentOptionsChanged}
onComponentClick={onComponentClick}
currentState={currentState}
containerProps={containerProps}
darkMode={darkMode}
removeComponent={removeComponent}
canvasWidth={canvasWidth}
readOnly={readOnly}
customResolvables={customResolvables}
parentId={parentId}
allComponents={allComponents}
extraProps={extraProps}
/>
</ErrorBoundary>
</div>
</Rnd>
</div>
) : (
<div ref={drag} role="DraggableBox" className="draggable-box" style={{ height: '100%' }}>
<Box
component={component}
id={id}
mode={mode}
inCanvas={inCanvas}
onEvent={onEvent}
paramUpdated={paramUpdated}
onComponentOptionChanged={onComponentOptionChanged}
onComponentOptionsChanged={onComponentOptionsChanged}
onComponentClick={onComponentClick}
currentState={currentState}
darkMode={darkMode}
removeComponent={removeComponent}
/>
<ErrorBoundary showFallback={mode === 'edit'}>
<Box
component={component}
id={id}
mode={mode}
inCanvas={inCanvas}
onEvent={onEvent}
paramUpdated={paramUpdated}
onComponentOptionChanged={onComponentOptionChanged}
onComponentOptionsChanged={onComponentOptionsChanged}
onComponentClick={onComponentClick}
currentState={currentState}
darkMode={darkMode}
removeComponent={removeComponent}
/>
</ErrorBoundary>
</div>
)}
</div>