Skip to content

Commit

Permalink
Merge pull request #41 from episerver/feature/AFORM-3699-Improve-code…
Browse files Browse the repository at this point in the history
…-to--optimize-re-render-react-component

Improve code to  optimize re-render react component
  • Loading branch information
hungoptimizely authored Nov 21, 2023
2 parents e089fc7 + a1ee9c3 commit 29706db
Show file tree
Hide file tree
Showing 16 changed files with 196 additions and 219 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Choice, equals, isNullOrEmpty } from "@optimizely/forms-sdk";
import React from "react";
import ElementWrapper from "../ElementWrapper";
import React, { useMemo } from "react";
import ElementWrapper from "./shared/ElementWrapper";
import { useElement } from "../../hooks/useElement";
import { ValidationMessage } from "./shared";

Expand All @@ -10,10 +10,11 @@ export interface ChoiceElementBlockProps {

export const ChoiceElementBlock = (props: ChoiceElementBlockProps) => {
const { element } = props;
const { elementContext, validatorClasses, handleChange, handleBlur, checkVisible } = useElement(element);
const { elementContext, handleChange, handleBlur } = useElement(element);
const { isVisible, validationResults, value, validatorClasses } = elementContext;

return (
<ElementWrapper className={`FormChoice ${validatorClasses}`} isVisible={checkVisible()}>
return useMemo(()=>(
<ElementWrapper className={`FormChoice ${validatorClasses}`} validationResults={validationResults} isVisible={isVisible}>
<fieldset aria-describedby={`${element.key}_desc`}>

{!isNullOrEmpty(element.properties.label) &&
Expand All @@ -22,8 +23,8 @@ export const ChoiceElementBlock = (props: ChoiceElementBlockProps) => {

{element.properties.items.map((item, index) => {
let isChecked = (!isNullOrEmpty(item.value)
&& !isNullOrEmpty(elementContext.value)
&& (elementContext.value).split(',').some((s: string) => equals(s, item.value))
&& !isNullOrEmpty(value)
&& (value).split(',').some((s: string) => equals(s, item.value))
);
let choiceId = `${element.key}_${index}`;

Expand Down Expand Up @@ -61,7 +62,7 @@ export const ChoiceElementBlock = (props: ChoiceElementBlockProps) => {
})}
</fieldset>

<ValidationMessage element={element} validationResults={elementContext.validationResults} />
<ValidationMessage element={element} validationResults={validationResults} />
</ElementWrapper>
);
),[isVisible, validationResults, value]);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FileUpload } from "@optimizely/forms-sdk"
import React from "react";
import ElementWrapper from "../ElementWrapper";
import React, { useMemo } from "react";
import ElementWrapper from "./shared/ElementWrapper";
import { useElement } from "../../hooks/useElement";
import { ElementCaption, ValidationMessage } from "./shared";

Expand All @@ -10,14 +10,15 @@ export interface FileUploadElementBlockProps {

export const FileUploadElementBlock = (props: FileUploadElementBlockProps) => {
const { element } = props;
const { elementContext, extraAttr, validatorClasses, handleChange, checkVisible } = useElement(element);
const { elementContext, handleChange } = useElement(element);
let allowedTypes = element.properties.fileTypes ? element.properties.fileTypes.split(",").map((ext) => {
ext = ext.trim();
return (ext[0] != ".") ? `.${ext}` : ext;
}).join(",") : "";
const { isVisible, validationResults, extraAttr, validatorClasses } = elementContext;

return (
<ElementWrapper className={`FormFileUpload ${validatorClasses}`} isVisible={checkVisible()}>
return useMemo(()=>(
<ElementWrapper className={`FormFileUpload ${validatorClasses}`} validationResults={validationResults} isVisible={isVisible}>
<ElementCaption element={element} />

<input
Expand All @@ -33,7 +34,7 @@ export const FileUploadElementBlock = (props: FileUploadElementBlockProps) => {
/>
<div className="FormFileUpload__PostedFile"></div>

<ValidationMessage element={element} validationResults={elementContext.validationResults} />
<ValidationMessage element={element} validationResults={validationResults} />
</ElementWrapper>
);
),[isVisible, validationResults]);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ImageChoice, equals, isNullOrEmpty } from "@optimizely/forms-sdk";
import React from "react";
import ElementWrapper from "../ElementWrapper";
import React, { useMemo } from "react";
import ElementWrapper from "./shared/ElementWrapper";
import { useElement } from "../../hooks/useElement";
import { ValidationMessage } from "./shared";

Expand All @@ -10,19 +10,21 @@ export interface ImageChoiceElementBlockProps {

export const ImageChoiceElementBlock = (props: ImageChoiceElementBlockProps) => {
const { element } = props;
const { elementContext, validatorClasses, handleChange, handleBlur, checkVisible } = useElement(element);
const { elementContext, handleChange, handleBlur } = useElement(element);
const sShouldBeVisible = element.properties.showSelectionInputControl ? "" : "visually-hidden";
return (
<ElementWrapper className={`FormChoice FormChoice--Image ${validatorClasses}`} isVisible={checkVisible()}>
const { isVisible, validationResults, value, validatorClasses } = elementContext;

return useMemo(()=>(
<ElementWrapper className={`FormChoice FormChoice--Image ${validatorClasses}`} validationResults={validationResults} isVisible={isVisible}>
<fieldset aria-describedby={`${element.key}_desc`}>
{
isNullOrEmpty(element.properties.label) &&
<legend className="Form__Element__Caption">{element.properties.label}</legend>
}
{element.properties.items.map((item, index) => {
let isChecked = (!isNullOrEmpty(item.text)
&& !isNullOrEmpty(elementContext.value)
&& (elementContext.value).split(',').some((s: string) => equals(s, item.text))
&& !isNullOrEmpty(value)
&& (value).split(',').some((s: string) => equals(s, item.text))
);
var imageChoiceId = element.key + index;
return <label htmlFor={imageChoiceId} className="FormChoice--Image__Item" key={element.key + item.text}>
Expand Down Expand Up @@ -59,7 +61,7 @@ export const ImageChoiceElementBlock = (props: ImageChoiceElementBlockProps) =>
</label>;
})}
</fieldset>
<ValidationMessage element={element} validationResults={elementContext.validationResults} />
<ValidationMessage element={element} validationResults={validationResults} />
</ElementWrapper>
);
),[isVisible, validationResults, value]);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Number } from "@optimizely/forms-sdk"
import React from "react";
import ElementWrapper from "../ElementWrapper";
import React, { useMemo } from "react";
import ElementWrapper from "./shared/ElementWrapper";
import { useElement } from "../../hooks/useElement";
import { ValidationMessage, ElementCaption } from "./shared";

Expand All @@ -10,10 +10,11 @@ export interface NumberElementBlockProps {

export const NumberElementBlock = (props: NumberElementBlockProps) => {
const { element } = props;
const { elementContext, extraAttr, validatorClasses, handleChange, handleBlur, checkVisible } = useElement(element);
const { elementContext, handleChange, handleBlur } = useElement(element);
const { isVisible, validationResults, value, extraAttr, validatorClasses } = elementContext;

return (
<ElementWrapper className={`FormTextbox FormTextbox--Number ${validatorClasses ?? ""}`} isVisible={checkVisible()}>
return useMemo(()=>(
<ElementWrapper className={`FormTextbox FormTextbox--Number ${validatorClasses}`} validationResults={validationResults} isVisible={isVisible}>
<div lang={element.locale}>
<ElementCaption element={element} />

Expand All @@ -24,15 +25,15 @@ export const NumberElementBlock = (props: NumberElementBlockProps) => {
step="any"
placeholder={element.properties.placeHolder}
{...extraAttr}
value={elementContext.value}
value={value}
aria-describedby={`${element.key}_desc`}
autoComplete={element.properties.autoComplete}
onChange={handleChange}
onBlur={handleBlur}
/>

<ValidationMessage element={element} validationResults={elementContext.validationResults} />
<ValidationMessage element={element} validationResults={validationResults} />
</div>
</ElementWrapper>
);
),[isVisible, validationResults, value]);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ interface PredefinedHiddenElementBlockProps {

export const PredefinedHiddenElementBlock = (props: PredefinedHiddenElementBlockProps) => {
const { element } = props;
const { elementContext, extraAttr } = useElement(element);

const { elementContext } = useElement(element);
const { value, extraAttr } = elementContext;

return (
<>
<input
name={element.key}
id={element.key}
type="hidden"
value={elementContext.value}
value={value}
className="Form__Element FormHidden FormHideInSummarized"
{...extraAttr}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Range } from "@optimizely/forms-sdk"
import React from "react";
import ElementWrapper from "../ElementWrapper";
import React, { useMemo } from "react";
import ElementWrapper from "./shared/ElementWrapper";
import { useElement } from "../../hooks/useElement";
import { ElementCaption, ValidationMessage } from "./shared";

Expand All @@ -10,13 +10,13 @@ export interface RangeElementBlockProps {

export const RangeElementBlock = (props: RangeElementBlockProps) => {
const { element } = props;
const { elementContext, validatorClasses, handleChange, handleBlur, checkVisible } = useElement(element);

const { elementContext, handleChange, handleBlur } = useElement(element);
const { isVisible, validationResults, value, validatorClasses } = elementContext;
const handleDecrement = () => {
handleChange({
target: {
name: element.key,
value: parseInt(elementContext.value) - element.properties.step,
value: parseInt(value) - element.properties.step,
type: "range",
}
})
Expand All @@ -26,18 +26,18 @@ export const RangeElementBlock = (props: RangeElementBlockProps) => {
handleChange({
target: {
name: element.key,
value: parseInt(elementContext.value) + element.properties.step,
value: parseInt(value) + element.properties.step,
type: "range",
}
})
}

return (
<ElementWrapper className={`FormRange ${validatorClasses}`} isVisible={checkVisible()}>
return useMemo(()=>(
<ElementWrapper className={`FormRange ${validatorClasses}`} validationResults={validationResults} isVisible={isVisible}>
<ElementCaption element={element} />
<span className="FormRange__Wrapper">
<span className="FormRange__Slider__Wrapper">
{elementContext.value > element.properties.min ?
{value > element.properties.min ?
<button className="FormRange__Slider__Button" type="button" aria-label="decrement" title="decrement" data-action="decrement" onClick={handleDecrement}>&lt;</button>
:
<button className="FormRange__Slider__Button FormRange__Slider__Button__Disable" type="button" aria-label="decrement" title="decrement" data-action="decrement">&lt;</button>
Expand All @@ -48,29 +48,29 @@ export const RangeElementBlock = (props: RangeElementBlockProps) => {
id={element.key}
type="range"
className="FormRange__Input"
value={elementContext.value}
value={value}
min={element.properties.min}
max={element.properties.max}
step={element.properties.step}
aria-valuemin={element.properties.min}
aria-valuemax={element.properties.max}
aria-valuenow={elementContext.value}
aria-valuetext={elementContext.value}
aria-valuenow={value}
aria-valuetext={value}
onChange={handleChange}
onBlur={handleBlur}
/>
<span className="FormRange__Max">{element.properties.max}</span>
{elementContext.value < element.properties.max ?
{value < element.properties.max ?
<button className="FormRange__Slider__Button" type="button" aria-label="increment" title="increment" data-action="increment" onClick={handleIncrement}>&gt;</button>
:
<button className="FormRange__Slider__Button FormRange__Slider__Button__Disable" type="button" aria-label="increment" title="increment" data-action="increment">&gt;</button>
}
</span>
<span className="FormRange__Output__Wrapper">
<output htmlFor={element.key} className="FormRange__Output">{elementContext.value}</output>
<output htmlFor={element.key} className="FormRange__Output">{value}</output>
</span>
</span>
<ValidationMessage element={element} validationResults={elementContext.validationResults} />
<ValidationMessage element={element} validationResults={validationResults} />
</ElementWrapper>
);
),[isVisible, validationResults, value]);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useMemo } from "react";
import { ResetButton } from "@optimizely/forms-sdk";
import { useElement } from "../../hooks/useElement";

Expand All @@ -8,9 +8,10 @@ interface ResetButtonElementBlockProps {

export const ResetButtonElementBlock = (props: ResetButtonElementBlockProps) => {
const { element } = props;
const { extraAttr, handleReset } = useElement(element);

return (
const { elementContext, handleReset } = useElement(element);
const { extraAttr } = elementContext;

return useMemo(()=>(
<>
<input
type="reset"
Expand All @@ -20,5 +21,5 @@ export const ResetButtonElementBlock = (props: ResetButtonElementBlockProps) =>
onClick={handleReset}
/>
</>
);
),[]);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Selection, isNullOrEmpty } from "@optimizely/forms-sdk"
import React from "react";
import ElementWrapper from "../ElementWrapper";
import React, { useMemo } from "react";
import ElementWrapper from "./shared/ElementWrapper";
import { useElement } from "../../hooks/useElement";
import { ElementCaption, ValidationMessage } from "./shared";

Expand All @@ -10,10 +10,11 @@ interface SelectionElementBlockProps {

export const SelectionElementBlock = (props: SelectionElementBlockProps) => {
const { element } = props;
const { elementContext, extraAttr, validatorClasses, handleChange, handleBlur, checkVisible } = useElement(element);

return (
<ElementWrapper className={`FormSelection ${validatorClasses}`} isVisible={checkVisible()}>
const { elementContext, handleChange, handleBlur } = useElement(element);
const { isVisible, validationResults, value, extraAttr, validatorClasses } = elementContext;

return useMemo(()=>(
<ElementWrapper className={`FormSelection ${validatorClasses}`} validationResults={validationResults} isVisible={isVisible}>
<ElementCaption element={element}></ElementCaption>
<select
name={element.key}
Expand All @@ -24,9 +25,9 @@ export const SelectionElementBlock = (props: SelectionElementBlockProps) => {
autoComplete={element.properties.autoComplete}
onChange={handleChange}
onBlur={handleBlur}
value={elementContext.value}
value={value}
>
<option value="" disabled={elementContext.value !== ""}>
<option value="" disabled={value !== ""}>
{isNullOrEmpty(element.properties.placeHolder)
? element.localizations["selectionDefaultPlaceholder"]
: element.properties.placeHolder
Expand All @@ -36,7 +37,7 @@ export const SelectionElementBlock = (props: SelectionElementBlockProps) => {
<option key={feed.value} value={feed.value} defaultChecked={feed.checked}>{feed.caption}</option>
))}
</select>
<ValidationMessage element={element} validationResults={elementContext.validationResults}></ValidationMessage>
<ValidationMessage element={element} validationResults={validationResults}></ValidationMessage>
</ElementWrapper>
);
),[isVisible, validationResults, value]);
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { SubmitButton, isNullOrEmpty } from "@optimizely/forms-sdk";
import React from "react";
import React, { useMemo } from "react";
import { useElement } from "../../hooks/useElement";
import ElementWrapper from "../ElementWrapper";
import ElementWrapper from "./shared/ElementWrapper";

interface SubmitButtonElementBlockProps{
element: SubmitButton
}

export const SubmitButtonElementBlock = (props: SubmitButtonElementBlockProps) => {
const { element } = props;
const { validatorClasses, extraAttr, checkVisible } = useElement(element);
const { elementContext } = useElement(element);
const { isVisible, extraAttr, validatorClasses } = elementContext;
//TODO: Need to get submittable status from API
const buttonDisableState = false;

return (
<ElementWrapper isVisible={checkVisible()}>
return useMemo(()=>(
<ElementWrapper isVisible={isVisible}>
<button id={element.key}
name="submit"
type="submit"
Expand All @@ -31,5 +32,5 @@ export const SubmitButtonElementBlock = (props: SubmitButtonElementBlockProps) =
)}
</button>
</ElementWrapper>
);
),[isVisible]);
}
Loading

0 comments on commit 29706db

Please sign in to comment.