首页 > 解决方案 > 更新 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;

标签: react-nativestateexporeact-native-flatlist

解决方案


应该避免突变,而不是在 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)}}/>
   )
}

推荐阅读