updating components

- using React.memo, removing React.forwardRef
- adding renderCount (to see which components are re-rendered)
- using ToggleButton instead of Button (might change again)
This commit is contained in:
Mose Müller 2023-08-02 12:06:19 +02:00
parent c13cd24a66
commit 01c748dcdc
2 changed files with 94 additions and 73 deletions

View File

@ -1,5 +1,5 @@
import React, { MouseEventHandler } from 'react'; import React, { MouseEventHandler, useEffect, useRef, useState } from 'react';
import { OverlayTrigger, Badge, Button, Tooltip } from 'react-bootstrap'; import { OverlayTrigger, Badge, Button, Tooltip, ToggleButton } from 'react-bootstrap';
interface ButtonComponentProps { interface ButtonComponentProps {
name: string; name: string;
@ -11,34 +11,43 @@ interface ButtonComponentProps {
mapping?: [string, string]; // Enforce a tuple of two strings mapping?: [string, string]; // Enforce a tuple of two strings
} }
const ButtonComponentRef = React.forwardRef<HTMLDivElement, ButtonComponentProps>( export const ButtonComponent = React.memo((props: ButtonComponentProps) => {
(props, ref) => { const renderCount = useRef(0);
const { name, fullname, value, readOnly, docString, onToggle, mapping } = props;
const buttonName = mapping ? (value ? mapping[0] : mapping[1]) : name; const [checked, setChecked] = useState(false);
const tooltip = <Tooltip id="tooltip">{docString}</Tooltip>; useEffect(() => {
renderCount.current++;
});
const { name, fullname, value, readOnly, docString, onToggle, mapping } = props;
return ( const buttonName = mapping ? (value ? mapping[0] : mapping[1]) : name;
<div className={'component boolean'} id={fullname} ref={ref}>
<Button
type={'button'}
variant={value ? 'success' : 'secondary'}
onMouseUp={onToggle}
disabled={readOnly}>
<p>{buttonName}</p>
</Button>
{docString && ( const tooltip = <Tooltip id="tooltip">{docString}</Tooltip>;
<OverlayTrigger placement="bottom" overlay={tooltip}>
<Badge pill className="tooltip-trigger" bg="light" text="dark">
?
</Badge>
</OverlayTrigger>
)}
</div>
);
}
);
export const ButtonComponent = React.memo(ButtonComponentRef); return (
<div className={'component boolean'} id={fullname}>
<p>Render count: {renderCount.current}</p>
<ToggleButton
id="toggle-check"
type="checkbox"
// variant="secondary"
variant={checked ? 'success' : 'secondary'}
checked={checked}
value={fullname}
onMouseUp={onToggle}
disabled={readOnly}
onChange={(e) => setChecked(e.currentTarget.checked)}>
<p>{buttonName}</p>
</ToggleButton>
{docString && (
<OverlayTrigger placement="bottom" overlay={tooltip}>
<Badge pill className="tooltip-trigger" bg="light" text="dark">
?
</Badge>
</OverlayTrigger>
)}
</div>
);
});

View File

@ -1,4 +1,4 @@
import React from 'react'; import React, { useEffect, useRef } from 'react';
interface ComponentProps { interface ComponentProps {
name: string; name: string;
@ -18,48 +18,60 @@ export const ComponentLabel = ({
return <label title={docString}>{name}</label>; return <label title={docString}>{name}</label>;
}; };
export const Component = ({ export const Component = React.memo(
name, ({ name, value, readOnly, type, docString }: ComponentProps) => {
value, const renderCount = useRef(0);
readOnly,
type, useEffect(() => {
docString renderCount.current++;
}: ComponentProps) => { });
switch (type) { switch (type) {
case 'int': case 'int':
case 'float': case 'float':
return ( return (
<input <>
type="number" <p>Render count: {renderCount.current}</p>
name={name} <input
value={value} type="number"
readOnly={readOnly} name={name}
title={docString} value={value}
/> readOnly={readOnly}
); title={docString}
case 'str': />
return ( </>
<input );
type="text" case 'str':
name={name} return (
value={value} <>
readOnly={readOnly} <p>Render count: {renderCount.current}</p>
title={docString} <input
/> type="text"
); name={name}
case 'bool': value={value}
return ( readOnly={readOnly}
<input title={docString}
type="checkbox" />
name={name} </>
checked={value} );
disabled={readOnly} case 'bool':
title={docString} return (
/> <input
); type="checkbox"
case 'method': name={name}
return <p>Method: {name}</p>; checked={value}
default: disabled={readOnly}
return <p>Unsupported type: {type}</p>; title={docString}
/>
);
case 'method':
return (
<>
<p>Render count: {renderCount.current}</p>
<p>Method: {name}</p>
</>
);
default:
return <p>Unsupported type: {type}</p>;
}
} }
}; );