#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
проверьте журнал консоли, чтобы увидеть состояние вывода.