I try to merge "Cache" and use "invalidatesTags" both in "createApi", but just one can working.
Merge cache working fine, but invalidatesTags in DeleteCollection for querySelect return nothing to merge or delete. Same problem with create but i temporarily fix it.
Can anyone help me. Thanks so much
Here is my createApi:
import {createApi, fetchBaseQuery} from '@reduxjs/toolkit/query/react';import config from '../../config.json';const API_URL = config.API_URL;const merchant = config.MERCHANT_NAME;const store = config.STORE;import {Collection} from '../../models/Collection.model';interface ListResponse<T> { offset: number; count: number; data: T[];}export const collectionApi = createApi({ reducerPath: 'collectionApi', baseQuery: fetchBaseQuery({ baseUrl: `${API_URL}/merchants/${merchant}/stores/${store}/`, }), tagTypes: ['Collections'], endpoints: builder => ({ getAllCollections: builder.query<ListResponse<Collection>, any>({ query: ({offset, limit}) => { let filter = encodeURIComponent( JSON.stringify({ offset: offset, limit: limit, }), ); return { url: `collections?filter=${filter}`, }; }, providesTags: (result, error, page) => { if (result) { return [ ...result.data.map(({id}) => ({type: 'Collections' as const, id})), {type: 'Collections', id: 'PARTIAL-LIST'}, ]; } else { return [{type: 'Collections', id: 'PARTIAL-LIST'}]; } }, serializeQueryArgs: ({queryArgs, endpointDefinition, endpointName}) => { return endpointName; }, merge: (currentCache, newItems) => { if (newItems.offset == currentCache.offset) { if ( newItems.count > currentCache.count && newItems.offset == currentCache.count ) { currentCache.data = currentCache.data.concat(newItems.data); } else if (currentCache.data == null) { currentCache.data = newItems.data; } currentCache.offset = newItems.offset; currentCache.count = newItems.count; } else if (newItems.offset > currentCache.offset) { currentCache.data = currentCache.data.concat(newItems.data); currentCache.offset = newItems.offset; currentCache.count = newItems.count; } }, forceRefetch({currentArg, previousArg}) { return currentArg !== previousArg; }, }), createCollection: builder.mutation<Collection, Partial<any>>({ query: data => ({ url: `collections/`, method: 'POST', body: data, }), invalidatesTags: (result, error, data) => { return [ {type: 'Collections', id: result?.id}, {type: 'Collections', id: 'PARTIAL-LIST'}, ]; }, }), updateCollection: builder.mutation<Collection, Partial<any>>({ query: ({data, id}) => ({ url: `collections/${id}`, method: 'PATCH', body: data, }), invalidatesTags: (result, error, {id}) => [ {type: 'Collections', id}, {type: 'Collections', id: 'PARTIAL-LIST'}, ], }), deleteCollection: builder.mutation<{success: boolean; id: number}, number>({ query: id => ({ url: `collections/${id}`, method: 'DELETE', }), invalidatesTags: (result, error, id) => [ {type: 'Collections', id}, {type: 'Collections', id: 'PARTIAL-LIST'}, ], }), }),});// Export hooks for usage in functional componentsexport const { useGetAllCollectionsQuery, useCreateCollectionMutation, useUpdateCollectionMutation, useDeleteCollectionMutation,} = collectionApi;
Here is where i used:
import React, {useEffect} from 'react';import { ActivityIndicator, Alert, Image, StyleSheet, Text, TouchableOpacity, View,} from 'react-native';import {FlatList} from 'react-native-bidirectional-infinite-scroll';import ButtonSmall from '../../components/ButtonSmall';import theme from '../../core/theme';import {Icon} from '@rneui/themed';import { useCreateCollectionMutation, useDeleteCollectionMutation, useGetAllCollectionsQuery,} from '../../redux/services/collection';const CollectionManagement = ({navigation}: any) => { //for infinite scroll const [offset, setOffset] = React.useState(0); const [limit, setLimit] = React.useState(10); //get collection const { data: allCollectionsData, error, isError, isLoading, refetch, } = useGetAllCollectionsQuery({offset: offset, limit: limit}); const onStartReached = async () => { // console.log('reload'); // await setOffset(0); // await refetch(); return; }; const onEndReached = async () => { if (allCollectionsData) { if (offset + limit > allCollectionsData.count) { await setOffset(allCollectionsData.count); } else { await setOffset(offset + limit); } } else { await setOffset(offset + limit); } await refetch(); return; }; //end infinite scroll const total = allCollectionsData?.count; const collectionList = allCollectionsData?.data; //delete collection const [ deleteCollection, {data: dataDelete, error: errorDelete, isSuccess: isSuccessDelete}, ] = useDeleteCollectionMutation(); //create collection const [ createCollection, {data: dataCreate, error: errorCreate, isSuccess: isSuccessCreate}, ] = useCreateCollectionMutation(); const deleteCollectionHandle = (id: any) => { Alert.alert('Thông báo', 'Bạn có chắc chắn muốn xoá danh mục này?', [ { text: 'Không', onPress: () => {}, }, { text: 'Có', onPress: () => { deleteCollection(id); }, }, ]); }; const doubleCollection = (data: any) => { let newData = { name: data.name, position: Number(data.position), description: data.description, internalName: data.internalName, }; createCollection(newData); }; return (<View style={styles.container}><View style={styles.header}><Text style={styles.title}>Danh sách danh mục</Text><Text style={styles.total}>Tổng số bản ghi: {total} </Text><ButtonSmall title="Thêm mới" onPress={() => { navigation.navigate('CollectionCreate'); }} /></View><View style={styles.body}> {isLoading ? (<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}><ActivityIndicator size="large" /></View> ) : (<FlatList data={collectionList} onEndReached={onEndReached} onStartReached={onStartReached} keyExtractor={(item: any) => item.id} renderItem={(data: any) => { let item = data.item; let url = item.preview; if (url === '') { url = 'https://petitemaika.com/brand.png'; } return (<View key={item.id} style={styles.item}><View style={styles.info}><Image source={{uri: url}} style={styles.image} /><View style={styles.detail}><Text style={styles.itemName} ellipsizeMode="middle" numberOfLines={2}> {item.name}</Text><Text style={styles.itemName} ellipsizeMode="middle" numberOfLines={1}> Tên rút gọn: {item.internalName}</Text><Text style={styles.itemName} ellipsizeMode="middle" numberOfLines={3}> Mô tả: {item.description}</Text><Text style={styles.itemName} ellipsizeMode="middle" numberOfLines={2}> Thứ tự: {item.position}</Text></View></View><View style={styles.action}><TouchableOpacity onPress={() => { navigation.navigate('CollectionEdit', item); }}><View style={styles.button}><Text style={styles.buttonText}>Sửa</Text><Icon name="pencil" type="ionicon" color={'white'} size={20} /></View></TouchableOpacity><TouchableOpacity onPress={() => { doubleCollection(item); }}><View style={styles.button}><Text style={styles.buttonText}>Nhân bản</Text><Icon name="copy" type="ionicon" color={'white'} size={20} /></View></TouchableOpacity><TouchableOpacity onPress={() => { deleteCollectionHandle(item.id); }}><View style={styles.button}><Text style={styles.buttonText}>Xoá</Text><Icon name="trash" type="ionicon" color={'white'} size={20} /></View></TouchableOpacity></View></View> ); }} /> )}</View></View> );};const styles = StyleSheet.create({ container: { flex: 1, }, header: { flex: 2, backgroundColor: theme.colors.BACKGROUND, justifyContent: 'space-between', alignItems: 'center', padding: 5, }, body: { flex: 8, backgroundColor: theme.colors.BACKGROUND, }, //text styles title: { fontSize: 20, fontWeight: 'bold', color: theme.colors.BLACK, }, total: { fontSize: 16, color: theme.colors.BLACK, }, itemName: { fontSize: 16, color: theme.colors.BLACK, }, //collection styles item: { flex: 1, margin: 10, borderColor: theme.colors.GREY, borderWidth: 1, borderRadius: 10, padding: 10, flexDirection: 'column', justifyContent: 'space-between', }, info: { flexDirection: 'row', flex: 1, }, action: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'flex-end', flex: 1, marginTop: 10, }, image: { width: 100, height: 100, borderRadius: 10, marginEnd: 10, }, button: { backgroundColor: theme.colors.PRIMARY, borderRadius: 7, alignItems: 'center', justifyContent: 'center', paddingVertical: 3, paddingHorizontal: 10, flexDirection: 'row', }, buttonText: { fontSize: 14, fontWeight: 'bold', color: theme.colors.WHITE, marginEnd: 5, }, detail: { flex: 1, flexDirection: 'column', },});export default CollectionManagement;