I have components like below
QuestionAnsPage.component(parent)
:
export interface FieldsDatatype {
id: string | number;
attributeId: string | number,
mainQuestionFlg?: boolean;
mainQuestionId: number | string,
question: string;
**values: Array<number | string>;**
fieldType: number;
mandatory: boolean;
isNumber: boolean;
pattern?: string;
max?: string | number;
min?: string | number;
displayInline?: boolean;
error?: boolean;
message?: string;
options: OptionsType[] | undefined | null;
storedColumn?: string;
storedJson?: string;
}
type Props = {
data?: FieldsDatatype[];
country: string;
handleOnConfirmClick: (data: FieldsDatatype[]) => void;
handleOnCancelClick: () => void;
isLoading?: boolean;
errorMessage?: Error;
id: string | number;
}
const QuestionAnsPageComponent = (props: Props): JSX.Element => {
const [data, setData] = useState([]);
useEffect(() => {
if (props.data) {
setData(props.data);
}
}, [props.data]);
.
.
..
}
My QuestionAnswer.componet(child):
type Props = {
data: FieldsDatatype;
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
onChangeSelect?: (id: string | number, value: string | number) => void;
onDateChange?: (fieldName: string | number, value: string) => void;
onBlur?: (event: React.FocusEvent<HTMLInputElement | HTMLButtonElement | HTMLTextAreaElement>) => void;
country: string;
}
const QuestionAnswerComponent = (props: Props): JSX.Element => {
function comparisonForRerender(prevProps: Props, nextProps: Props): boolean {
console.log('nextProps:', nextProps.data.values, nextProps.data.id);
console.log('prevProps:', prevProps.data.values, prevProps.data.id);
const nextValArr = [...nextProps.data.values];
const prevValArr = prevProps.data ? [...prevProps.data.values] : [];
const nextValuesLen = nextValArr.length;
const prevValuesLen = prevValArr.length;
if (nextValArr
&& prevValArr
&& nextValuesLen > 1
&& nextProps.data.fieldType === FIELDS_TYPE.CHECKBOX) {
return (nextValuesLen === prevValuesLen
&& JSON.stringify(prevValArr) === JSON.stringify(prevValArr));
} else if (nextValArr
&& prevValArr
&& nextValuesLen > 0
&& prevValuesLen > 0
&& nextProps.data.id === prevProps.data.id) {
**return (prevValArr.includes(nextValArr[0]));**
}
return false;
}
}
export default React.memo(QuestionAnswerComponent, comparisonForRerender);
I am using this React.memo
for performance improvement. I want to render my child component when "props.data.values"
(type of this field is Array<string | number>
) changes. for that purpose I have created comparisonForRerender
function.
I am trying to compare props.data.value
in function like :(prevValArr.includes(nextValArr[0]))
But this function causing some weird behavior, my parent component state get reset to old value some how(data in this case).
I am not sure but this comparison function somehow changing my parent component state. If I remove this function then it is working fine.
Your parent component is being updated because
props.data
is an array. Only the pointer of the array is checked in the dependency array, of theuseEffect
function, you'll need to compare value of every element in the array, or choose a different a dependency variable, maybe something like the length of the array.