react-native - 更新 FlatList renderItem() 中的主要状态
问题描述
我正在构建一种列表应用程序,我希望用户在单击 TouchableOpacity 时更改状态。状态包含应该使用名为重复的属性单击多少次,例如,如果该重复是 (5) 我希望用户在单击时更改为 (4) 等等
我尝试了很多方法来解决它,但不幸的是没有任何效果有人可以帮忙吗?
import React, {useState, useEffect ,useCallback} from 'react';
import {View,
Text,
StyleSheet,
FlatList ,
TouchableOpacity,
ImageBackground,
Dimensions,
} from 'react-native';
import Spacer from '../components/Spacer';
import Audio from '../components/Audio';
import myApi from '../APIs/myApi';
const SCREEN_WIDTH = Dimensions.get('window').width;
const SCREEN_HEIGHT = Dimensions.get('window').height;
const ShowScreen = ({ navigation }) => {
const [text, setText] = useState({});
const [repeat, setRepeat] = useState();
const id = navigation.getParam('id');
const title = navigation.getParam('title');
const Api = async() => {
const response = await myApi.get(`/${id}`);
setText(response.data);
};
useEffect(() => {
Api();
} , []);
return (
<View style={styles.container}>
<Text style = {styles.textHead}> {title} </Text>
<FlatList
data = {text.content}
keyExtractor = {(text) => text.id}
renderItem = {({item}) => {
return (
<View style = {styles.listContainer}>
<TouchableOpacity onPress = {() => item.repeat = item.repeat - 1}>
<Text style= {styles.textList}> {item.text} </Text>
<Spacer />
<Audio link = {item.audio_url} />
</TouchableOpacity>
<View style = {styles.repeatContianer} >
<Text> {item.repeat} </Text>
</View>
</View>
);
}}
extraData = {text.repeat}
/>
</View>
);
};
const styles = StyleSheet.create({
container : {
flex : 1,
alignItems : 'center',
marginTop : 15,
},
textHead : {
fontSize : 26,
textDecorationLine : 'underline',
fontWeight : 'bold'
},
textList : {
fontSize : 20,
fontStyle : 'italic',
margin : 5,
alignSelf: 'center',
justifyContent : 'center',
},
listContainer : {
borderWidth : 1 ,
justifyContent : 'center',
alignItems : 'center',
margin : 5,
borderRadius : 7
},
repeatContianer : {
flex: 1,
borderWidth : 1.5,
borderRadius : 5,
borderColor : 'red',
margin : 5
},
backGround : {
flex: 1,
resizeMode: "cover",
justifyContent: "center",
width : SCREEN_WIDTH,
height : SCREEN_HEIGHT,
opacity : 0.4
}
});
export default ShowScreen;
解决方案
应该避免突变,而不是在 onPress 中写入 item.repeat = item.repeat - 1,您应该将其提升一步,您的 renderItem 应该更改为类似
renderItem = {({item, index}) => {
return (
<View style = {styles.listContainer}>
<TouchableOpacity onPress = {() => _handleOnPress({item, index})}>
<Text style= {styles.textList}> {item.text} </Text>
<Spacer />
<Audio link = {item.audio_url} />
</TouchableOpacity>
<View style = {styles.repeatContianer} >
<Text> {item.repeat} </Text>
</View>
</View>
);
}}
比在_handleOnPress中,您可以进行状态更新
_handleOnPress =({item, index})=>{
//add necessary checks for current or index
const contentCopy = text.content; //created a copy
const current = contentCopy[index];
const updatedContent = [...contentCopy.slice(0, index), //finding and updating only current item
{...current, repeat:current.repeat-1}...contentCopy.slice(index+1)];
setText({...text, content:updatedContent});
}
或者您应该将您的 renderItem 创建为不同的组件并在其中处理更新,类似于
const ListItem =({item, index})=>{
const [repeat, setRepeat]= React.useState(item.repeat);
return(
<Your_UI_Goes_Here onPress={()=>{setRepeat(repeat-1)}}/>
)
}
推荐阅读
- angular - 角慢加载初始页面
- php - Laravel 多对多关系返回空数组
- django - 使用 Jinja / Django 显示 Algolia 结果
- php - 我的buddypress自定义标签代码有什么问题?
- php - 如何使用内容类型为 EAN-13 的 php 创建条形码
- python - 如何确定 sshd 的这个 perl 脚本的标准输入内容
- python - 仅将值复制到具有列名的新空数据框 - Pandas
- angular - 为 Angular 6 自定义 Angular Material Datepicker 大小
- angular - 如何不让 mat-sidenav-content 占用网页上的空白空间
- amazon-s3 - 从 MapR 到 Amazon S3 的数据迁移