【问题标题】:React Native Flatlist Not updating after context changedReact Native Flatlist 在上下文更改后不更新
【发布时间】:2020-07-04 06:13:13
【问题描述】:

我的 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

【问题讨论】:

    标签: reactjs react-native react-hooks react-native-flatlist


    【解决方案1】:

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

    ...
    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() 添加到所有屏幕

    【讨论】:

      【解决方案2】:

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

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

          setListItemsRefresh(listItemsRefresh => !listItemRefresh)
      

      【讨论】:

        【解决方案3】:

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

        【讨论】:

        • 完成了,没有帮助!
        • @mrgeek 如果您使用“完成”的代码更新您的问题并解释“什么没有帮助!”,这将很有帮助。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-04
        • 1970-01-01
        相关资源
        最近更新 更多