Как перерисовать элемент, нажав на него expo js?

У меня есть плоский список с отображаемым списком элементов. Мне нужно, чтобы каждый элемент менял круг на отмеченный круг при нажатии и возвращался при втором щелчке. Я попытался сделать это, изменив свойство элемента 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>
);

Вы можете предоставить весь файл js/jsx?

baymax 11.12.2020 20:37
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
1
258
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В этой строке вы пытаетесь изменить переменную реквизита, поэтому реакция не будет обновлять компонент при изменении состояния реквизита.

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>;
};

Другие вопросы по теме