How do I avoid mapped child components from re-rendering at onParent
state change?
I have already tried memo
in child component and useCallback
in parent component to memoise function that updates the state with an empty array as dependencies. I have also tried to use option?.id
as a key to each child component. None of these seem to work.
Parent.js
// imports and stuff
const [passedAnswers, setPassedAnswers] = useState(item?.options);
// const [showScore, setShowScore] = useState(false);
console.log("===========Parent component called ======================");
// const [correct, setCorrect] = useState(false);
const changeAnswer = useCallback((id) => {
setPassedAnswers((prev) =>
prev.map(
(el) => (el?.id === id ? { ...el, isSeclected: !el?.isSeclected } : el)
)
);
}, []);
return (<>
{
passedAnswers?.map((option, index) => {
return (
<CheckBoxQuiz
key={option?.id}
value={option}
index={index}
isSelected={!!option?.isSeclected}
changeAnswer={changeAnswer}
disabled={answered}
/>
);
})
}
</>)
QuizBox.js
import React, { memo, useEffect } from "react";
import { View, Text } from "react-native";
import { ICONS } from "../../assets";
import { TouchableBloc } from "../../components/bloc";
import { theme } from "../../constants/theme";
function CheckBoxQuiz({
value,
isSelected = false,
changeAnswer,
disabled = false,
}) {
const color =
isSelected == true && value.isCorrect == true
? theme.COLORS.green
: isSelected == false && value.isCorrect == true
? theme.COLORS.green
: "red";
console.log(`==child component called ${value.id}==`);
return (
<TouchableBloc
// key=r{index}
onPress={() => {
changeAnswer(value?.id);
}}
disabled={disabled}
containerStyle={{
marginHorizontal: 0,
flexDirection: "row",
borderRadius: 10,
borderColor: disabled
? color
: isSelected
? theme.COLORS.green
: "#E6E6E6",
borderWidth: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: isSelected && "#FAFFF9",
marginVertical: 5,
}}
>
<Text
style={{
flexGrow: 0.98,
flex: 1,
fontFamily: theme.FONTS.PoppinsSemiBold,
fontSize: 16,
}}
>
{value?.value}
</Text>
<View
style={{
width: 20,
height: 20,
borderWidth: 1,
borderColor: disabled
? color
: isSelected
? theme.COLORS.green
: "#E8E8E8",
borderRadius: 5,
justifyContent: "center",
alignItems: "center",
}}
>
{isSelected && (
<Icon
name="check"
size={10}
color={disabled ? color : theme.COLORS.green}
/>
)}
</View>
</TouchableBloc>
);
}
export default memo(CheckBoxQuiz);