У меня есть плоский список с отображаемым списком элементов. Мне нужно, чтобы каждый элемент менял круг на отмеченный круг при нажатии и возвращался при втором щелчке. Я попытался сделать это, изменив свойство элемента isChecked, но круг не перерисовывается, пока я не выйду из экрана и не вернусь. Как я могу решить мою проблему?
Вот мой код рендеринга:
const renderItems = ({ item }) => (
<TouchableOpacity
onPress = {() => (item.isChecked = !item.isChecked)}
style = {
item.isMarked
? {
backgroundColor: '#FE2C55',
flexDirection: 'row',
alignItems: 'center',
height: word_height
}
: { flexDirection: 'row', alignItems: 'center', height: word_height }
}
>
<View
style = {{
width: 45,
justifyContent: 'center',
alignItems: 'center',
height: '100%',
backgroundColor: '#F6FFE0'
}}
>
{item.isChecked ? (
<Feather name = "check-circle" size = {25} color = "#3D5201" />
) : (
<Feather name = "circle" size = {25} color = "#3D5201" />
)}
</View>
<View style = {styles.word_line}>
<View style = {{ width: word_width, paddingLeft: 20 }}>
<Text style = {{ fontSize: 20 }}>{item.word}</Text>
</View>
<View style = {{ width: word_width, paddingLeft: 20 }}>
<Text style = {{ fontSize: 20 }}>{item.translation}</Text>
</View>
</View>
</TouchableOpacity>
);
В этой строке вы пытаетесь изменить переменную реквизита, поэтому реакция не будет обновлять компонент при изменении состояния реквизита.
onPress = {() => (item.isChecked = !item.isChecked)}
Для этого создадим отдельный компонент (исходя из названия метода renderItems
, наверное, это просто функция в компоненте) и добавим в него состояние.
Используйте useState
и начальное значение состояния, которое было взято из реквизита initialIsChecked
const Item = ({isMarked, isChecked: initialIsChecked, word, translation}) => {
const [isChecked, setIsChecked] = useState(initialIsChecked);
const handleClick = () => {
setIsChecked((prev) => !prev);
};
return (
<TouchableOpacity
onPress = {handleClick}
style = {
isMarked
? {
backgroundColor: '#FE2C55',
flexDirection: 'row',
alignItems: 'center',
height: word_height,
}
: {flexDirection: 'row', alignItems: 'center', height: word_height}
}>
<View
style = {{
width: 45,
justifyContent: 'center',
alignItems: 'center',
height: '100%',
backgroundColor: '#F6FFE0',
}}>
{isChecked ? (
<Feather name = "check-circle" size = {25} color = "#3D5201" />
) : (
<Feather name = "circle" size = {25} color = "#3D5201" />
)}
</View>
<View style = {styles.word_line}>
<View style = {{width: word_width, paddingLeft: 20}}>
<Text style = {{fontSize: 20}}>{word}</Text>
</View>
<View style = {{width: word_width, paddingLeft: 20}}>
<Text style = {{fontSize: 20}}>{translation}</Text>
</View>
</View>
</TouchableOpacity>
);
};
Тогда компонент списка должен выглядеть примерно так:
const List = () => {
return <ScrollView>
items.map((item) => (
<Item
key = {item.id} // if there is id
isMarked = {item.isMarked}
isChecked = {item.isChecked}
word = {item.word}
translation = {item.translation}
/>
)
</ScrollView>;
};
Вы можете предоставить весь файл js/jsx?