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

时间:2020-07-04 06:13:13

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

我的App函数中有一个NavigationContainer,其中包含两个函数:Home和Cart。 当我单击“主页”中的一个项目时,其计数首次在“购物车”列表中更新,但是在第一次之后,数据会更新,但该平面列表直到单击后才会更新!!

我的App功能:

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;

我想要做的就是在更改计数后更新单位列表。 Tnx

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

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

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

    setListItemsRefresh(listItemsRefresh => !listItemRefresh)

答案 2 :(得分:0)

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