Изменение состояния только для нажатого элемента

#javascript #react-native

#javascript #react-native

Вопрос:

В моем приложении react-native у меня есть функция, которая изменяет состояние нажатого элемента с false на true, но проблема в том, что она изменяет состояние для всех элементов, а не только для нажатого, я хочу, чтобы при нажатии оно менялось только для нажатого элемента в моем FlatList, вот код:

Начальное состояние:

 state={pressed: false}
  

Функция:

 changeItem = async item => {this.setState({ pressed: true });};
  

Визуализация элемента и привязка функции:

 _renderItem({ item, index }) {
   <TouchableOpacity onPress={this.changeItem.bind(this, item)}>
     <Text> Click me </Text>
   </TouchableOpacity>
   );
}
  

Плоский список:

 <FlatList data={this.state.items}
          keyExtractor={this._keyExtractor.bind(this)}
          renderItem={this._renderItem.bind(this)}/>
  

Комментарии:

1. Для каждого элемента требуется нажатый реквизит. Вы можете изменить свое состояние с простого логического значения на массив логических значений, по одному для каждого элемента вашего flatlist

2. @Milore можете ли вы опубликовать как в качестве ответа, пожалуйста?

3. it's changing the state for all of the items где другие итены? Вы используете FlatList или что-то в этомроде? Если да, пожалуйста, предоставьте остальную часть кода.

4. @Vencovsky обновлено

Ответ №1:

Проблема здесь в том, что у вас есть список элементов, но все они имеют одинаковое состояние.

Вам нужен список элементов (массив), но вам также нужен массив состояния элементов.

Итак, вместо state = { pressed: false } вам нужно state = { pressed: []}

И при рендеринге элементов вам нужно передать индекс нажатой кнопки:

 _renderItem({ item, index }) {
   return this.state.pressed[index] amp;amp;
       <TouchableOpacity onPress={this.changeItem.bind(this, item, index)}>
          <Text> Click me </Text>
       </TouchableOpacity>
}
  

И обновите состояние только в выбранном индексе

 changeItem = async (item, index) => {
    let itensPressed = this.state.pressed
    itensPressed[index] = itensPressed[index] ? false : true
    this.setState({ pressed: itensPressed })
}
  

Но есть кое-что получше, чем делать это.

Я вижу, что вы получаете items из state , поэтому, возможно, вы хотите обновить items массив, а не создавать другую переменную.

Это зависит от того, как ваш this.state.items поступает, и можете ли вы или не можете иметь isPressed значение в этом массиве.

Если вы покажете, как продвигается ваша items работа, я смогу создать лучший ответ.

Комментарии:

1. этот ответ по-прежнему изменяет состояние для всех элементов, я получаю элементы из выборки вызова и показываю их условно на основе нажатого состояния

2. Покажите, где в коде вы это делаете: showing them conditionally based on the pressed state

3. Можете ли вы сохранить, нажат ли элемент в this.state.items ?

4. и я показываю их условно внутри элемента рендеринга следующим образом {!this.state.pressed ? <TouchableOpacity onPress={this.changeItem.bind(this, item, index)}> <Text> Click me </Text> </TouchableOpacity> : null}

5. @MonicaJennings вам нужно проверить this.state.pressed[index] . Смотрите мои правки

Ответ №2:

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

Сделайте это следующим образом.

 import React, {Component} from 'react';
import { FlatList, TouchableOpacity, Text} from 'react-native';

sampleData = [
  {key: 0, pressed: false},
  {key: 1, pressed: false},
  {key: 2, pressed: false}
]

export default class Example extends Component {

  state={
    data: sampleData
  }

  componentDidUpdate(){
    console.log(this.state.data)
  }

  changeItem(item)
  {
    this.setState( (prevState) => {
      prevState.data[item.key] = { ...item, pressed: !item.pressed}
      return{
        ...prevState,
        data: [...prevState.data]
      }
      });
  };  



  _keyExtractor = (item, index) => item.key;

  _renderItem({ item, index }) {
    return(
      <TouchableOpacity onPress={this.changeItem.bind(this,item)}>
      <Text> Click me </Text>
    </TouchableOpacity>
    )

 }

  render() {
    const {data} = this.state
      return (
        <FlatList
        data={data}
        keyExtractor={this._keyExtractor}
        renderItem={this._renderItem.bind(this)}
      />
      )
    }
  }
  

я просто создаю массив объектов, содержащий свойство key и pressed, и передаю его в state.data

проверьте журнал консоли, чтобы увидеть состояние вывода.