React Native Flatlist 在上下文更改后不更新

React Native Flatlist Not updating after context changed

我的 App 函数中有一个 navigationContainer,它包含两个函数:Home 和 Cart。 当我点击主页中的一个项目时,它的数量第一次在购物车列表中更新,但是第一次之后,数据更新但平面列表直到点击才更新!!

我的应用程序功能:

export let ListDataContext = React.createContext(basketData);
const Tab = createBottomTabNavigator();
export default function App() {
    const [context, setContext] = useState(basketData);
    return (

        <ListDataContext.Provider value={[context, setContext]}>
            <NavigationContainer>

                <Tab.Navigator screenOptions={({route}) => ({
                    tabBarIcon: ({focused, color, size, isVisible}) => {
                        let iconName;

                        if (route.name === 'Home') {

                            isVisible = 'none';
                            iconName = focused
                                ? 'home'
                                : 'home';
                        } else if (route.name === 'Cart') {

                            iconName = focused ? 'shopping-cart' : 'shopping-cart';
                        }
                        // You can return any component that you like here!
                        return <IconWithBadge name={iconName} color={'#ff9900'}
                                              badgeCount={23} size={21}
                                              visibility={isVisible}/>;
                    },
                })}
                               tabBarOptions={{
                                   activeTintColor: 'tomato',
                                   inactiveTintColor: 'gray',
                               }}
                >

                    <Tab.Screen name="Home" component={HomeStackScreen}/>
                    <Tab.Screen name="Cart" component={CartStackScreen}/>

                </Tab.Navigator>

            </NavigationContainer>
</ListDataContext.Provider>


    );
}

我的首页功能:

function ListItem({id, name, count, handleClicks}) {
    return useMemo(() => {
        return (
            <TouchableNativeFeedback onPress={() =>
                handleClicks(id)}>
                <Container style={{
                    width: '100%', height: 180,
                    backgroundColor: '#FEFFFF', alignSelf: 'center'
                }}>
                    <Content>


                        <View style={{
                            width: '95%', height: 170,
                            flexDirection: 'row', borderRadius: 10, elevation: 3,
                            padding: 10, marginBottom: 5
                        }}>

                            <View style={{
                                width: 100, height: '100%',
                                justifyContent: 'center', marginLeft: 10
                            }}>

                                <Image style={{width: '100%', height: 100, borderRadius: 50}}
                                       source={require('../images/imgprofile.jpg')}
                                />
                            </View>
                            <View style={{flex: 1, flexDirection: 'column'}}>
                                <Text style={{marginLeft: 20, marginTop: 30, fontSize: 18}}>
                                    {name}
                                </Text>
                                <Text style={{marginLeft: 20, fontSize: 28}}
                                      onPress={() => console.log('d')}>
                                    +
                                </Text>
                                <Text style={{marginLeft: 20, marginTop: 5, fontSize: 18}}>
                                    {count}
                                </Text>
                                <Text style={{marginLeft: 20, fontSize: 28}}>
                                    -
                                </Text>
                            </View>
                        </View>

                    </Content>
                </Container>
            </TouchableNativeFeedback>

        );
    },  [id, name, count, handleClicks]);

}

function HomeScreen({navigation}) {
    const [context, setContext] = useContext(ListDataContext);
    const [listItemsRefresh, setListItemsRefresh] = useState(false);
    const handleClicks = (id)  => {
        for (let i = 0; i < context.length; i++){
            if (context[i]['id'] === id){
                context[i]['count'] = context[i]['count'] + 1;
                setContext(context);
            }
        }
        setListItemsRefresh(!listItemsRefresh);
        setContext(context);
        console.log(context);
    };

    return (

        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>

            <SafeAreaView style={{ marginBottom: 10,
                width: '90%', height: '90%',
                alignContent: 'center'}}>
                <FlatList
                    data={context}
                    renderItem={({item}) => <ListItem
                        id={item.id}
                        name={item.name}
                        count={item.count}
                        handleClicks={handleClicks}
                    />}
                    keyExtractor={item => item.id}
                    extraData={listItemsRefresh}
                />
            </SafeAreaView>

        </View>

    );

}


export default HomeScreen;

我的购物车功能:

function ListItem({id, name, count, handleClicks}) {

    return useMemo(() => {
        return (
            <TouchableNativeFeedback onPress={() =>
                handleClicks(id)}>
                <Container style={{
                    width: '100%', height: 180,
                    backgroundColor: '#FEFFFF', alignSelf: 'center'
                }}>

                    <View style={{
                        width: '95%', height: 170,
                        flexDirection: 'row', borderRadius: 10, elevation: 3,
                        padding: 10, marginBottom: 5
                    }}>

                        <View style={{
                            width: 100, height: '100%',
                            justifyContent: 'center', marginLeft: 10
                        }}>

                            <Image style={{width: '100%', height: 100, borderRadius: 50}}
                                   source={require('../images/imgprofile.jpg')}
                            />
                        </View>
                        <View style={{flex: 1, flexDirection: 'column'}}>
                            <Text style={{marginLeft: 20, marginTop: 30, fontSize: 18}}>
                                {name}
                            </Text>
                            <Text style={{marginLeft: 20, fontSize: 28}}
                                  onPress={() => console.log('d')}>
                                +
                            </Text>
                            <Text style={{marginLeft: 20, marginTop: 5, fontSize: 18}}>
                                {count}
                            </Text>
                            <Text style={{marginLeft: 20, fontSize: 28}}>
                                -
                            </Text>
                        </View>
                    </View>


                </Container>
            </TouchableNativeFeedback>

        );
    }, [id, name, count, handleClicks]);

}

function DetailScreen() {
    const [context, setContext] = useContext(ListDataContext);
    const [listItemsRefresh, setListItemsRefresh] = useState(true)
    const handleClicks = (id)  => {
        for (let i = 0; i < context.length; i++){
            if (context[i]['id'] === id){
                context[i]['count'] = context[i]['count'] - 1;
                setContext(context);
            }
        }
        setListItemsRefresh(!listItemsRefresh);
        setContext(context);
        //navigation.navigate('Home');
        console.log(context);
    };
    return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>

            <SafeAreaView style={{ marginBottom: 10,
                width: '90%',
                alignContent: 'center'}}>
                <FlatList
                    data={context}
                    renderItem={({item}) => <ListItem
                        id={item.id}
                        name={item.name}
                        count={item.count}
                        handleClicks={handleClicks}
                    />}
                    keyExtractor={item => item.id}
                    extraData={listItemsRefresh}
                />
            </SafeAreaView>

        </View>
    );
}

export default DetailScreen;

我只想在Count改变后更新flatlist。 Tnx

你不应该改变状态,你可以使用传播:{...state,prop:'newValue'}和数组方法map and filter or use immer

经过2天的挣扎,我终于得到了答案! “@react-navigation/native”包中有一个名为 useIsFocused 的道具,它确定屏幕是否聚焦(正在显示)。因此,为了重新呈现 FlatList,您所要做的就是在屏幕函数中调用 useIsFocused()。 现在我的主屏幕看起来像这样:

...
import { useIsFocused} from '@react-navigation/native'; 
...

function HomeScreen() {
    const [context, setContext] = useContext(ListDataContext);
    const [listItemsRefresh, setListItemsRefresh] = useState(false);
    const handleClicks = (id)  => {
        for (let i = 0; i < context[0].data.length; i++){
            if (context[0].data[i]['id'] === id){
                context[0].data[i]['count'] = context[0].data[i]['count'] + 1;
                context[0].badgeCount = context[0].badgeCount + 1;
            }
        }
        setListItemsRefresh(!listItemsRefresh);
        console.log(context[0].listRefresh)
        console.log(context);
    };

    //Add this line to tell the function that it's in focuse
    useIsFocused();

    return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
            <SafeAreaView style={{ marginBottom: 10,
                width: '90%', height: '90%',
                alignContent: 'center'}}>
                <FlatList
                    data={context[0].data}
                    renderItem={({item}) => <ListItem
                        id={item.id}
                        name={item.name}
                        count={item.count}
                        handleClicks={handleClicks}
                    />}
                    keyExtractor={item => item.id}
                    extraData={listItemsRefresh}
                />
            </SafeAreaView>
        </View>
    );
}
export default HomeScreen;

现在将 useIsFocused() 添加到您的所有屏幕

我认为这不是更新状态的正确方法:

如果你想更新依赖于过去状态的状态,你应该这样做:

    setListItemsRefresh(listItemsRefresh => !listItemRefresh)