Files
pydase/frontend/src/components/StringComponent.tsx
Mose Müller b1e6663c66 frontend: introduces useRenderCount hook
The useRenderCount hook contains all the necessary logic to count the re-render events.
This reduces duplication and code complexity.
2024-07-08 15:10:37 +02:00

108 lines
2.9 KiB
TypeScript

import React, { useEffect, useState } from "react";
import { Form, InputGroup } from "react-bootstrap";
import { DocStringComponent } from "./DocStringComponent";
import "../App.css";
import { LevelName } from "./NotificationsComponent";
import { SerializedObject } from "../types/SerializedObject";
import { useRenderCount } from "../hooks/useRenderCount";
// TODO: add button functionality
interface StringComponentProps {
fullAccessPath: string;
value: string;
readOnly: boolean;
docString: string | null;
isInstantUpdate: boolean;
addNotification: (message: string, levelname?: LevelName) => void;
changeCallback?: (value: SerializedObject, callback?: (ack: unknown) => void) => void;
displayName: string;
id: string;
}
export const StringComponent = React.memo((props: StringComponentProps) => {
const {
fullAccessPath,
readOnly,
docString,
isInstantUpdate,
addNotification,
changeCallback = () => {},
displayName,
id,
} = props;
const renderCount = useRenderCount();
const [inputString, setInputString] = useState(props.value);
useEffect(() => {
// Only update the inputString if it's different from the prop value
if (props.value !== inputString) {
setInputString(props.value);
}
addNotification(`${fullAccessPath} changed to ${props.value}.`);
}, [props.value]);
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setInputString(event.target.value);
if (isInstantUpdate) {
changeCallback({
type: "str",
value: event.target.value,
full_access_path: fullAccessPath,
readonly: readOnly,
doc: docString,
});
}
};
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === "Enter" && !isInstantUpdate) {
changeCallback({
type: "str",
value: inputString,
full_access_path: fullAccessPath,
readonly: readOnly,
doc: docString,
});
event.preventDefault();
}
};
const handleBlur = () => {
if (!isInstantUpdate) {
changeCallback({
type: "str",
value: inputString,
full_access_path: fullAccessPath,
readonly: readOnly,
doc: docString,
});
}
};
return (
<div className="component stringComponent" id={id}>
{process.env.NODE_ENV === "development" && <div>Render count: {renderCount}</div>}
<InputGroup>
<InputGroup.Text>
{displayName}
<DocStringComponent docString={docString} />
</InputGroup.Text>
<Form.Control
type="text"
name={id}
value={inputString}
disabled={readOnly}
onChange={handleChange}
onKeyDown={handleKeyDown}
onBlur={handleBlur}
className={isInstantUpdate && !readOnly ? "instantUpdate" : ""}
/>
</InputGroup>
</div>
);
});
StringComponent.displayName = "StringComponent";