I’m working with an API endpoint that returns random data for a particular property (unstableProperty) every time it is called for the same entity. This behavior is illustrated below:
// First API Call
GET /entities/3
{
"name": "Entity Name",
"message": "This is some entity description",
"files": [
{ "fileName": "File1", "unstableProperty": "bbserg" },
{ "fileName": "File2", "unstableProperty": "thslkuygseaf" }
]
}
// Second API Call (5 seconds later)
GET /entities/3
{
"name": "Entity Name",
"message": "This is some entity description",
"files": [
{ "fileName": "File1", "unstableProperty": "ystgrgazazrg" },
{ "fileName": "File2", "unstableProperty": "strhsryjarehaerh" }
]
}
Context
A business rule requires polling this endpoint every X seconds for changes. However, I do not want my component to refresh every time as it includes a table with potentially hundreds of rows, and each row includes a thumbnail. Rerendering the table each time causes performance issues and makes the thumbnails flicker.
Issue
I’m attempting to use this example from RTKQuery documentation to prevent rerendering but it looks like this does not work as intended. Despite setting up a selector that filters out the unstable properties, the component still rerenders every polling interval.
I prepared a detailed example on this codesandbox: https://codesandbox.io/p/sandbox/modest-snyder-vyxkxd?file=%252Fsrc%252Fapi%252FbaseApi.ts
Here is how I have simulated the unstable property for demonstration:
let calls = 0;
export const baseApi = createApi({
baseQuery: fetchBaseQuery(),
endpoints: (build) => ({
getTestData: build.query<TestDataResponse, void>({
queryFn: () => ({
data: {
name: "Entity Name",
message: "This is some entity description",
files: [
{ fileName: "File1", unstableProperty: `value_${calls++}` },
{ fileName: "File2", unstableProperty: `value_${calls++}` },
],
},
}),
}),
}),
});
My component that shows the issue utilizes this query in the following way:
const selectOnlyStableData = useMemo(() => {
return createSelector(
(data: TestDataResponse | undefined) => data,
(data: TestDataResponse | undefined) => {
if (!data) return undefined;
// Select everything from data except files' unstableProperty
const stableData = {
name: data.name,
message: data.message,
files: data.files.map((f) => ({
fileName: f.fileName,
})),
};
return stableData;
}
);
}, []);
const { data } = useGetTestDataQuery(undefined, {
pollingInterval: 5000,
selectFromResult: ({ data }) => ({
data: selectOnlyStableData(data),
}),
});
Despite the selector, the component rerenders every 5 seconds. Everything works as intended if I remove the unstableProperty from the query result entirely.
Question
How can I prevent rerenders caused by changes to unstableProperty while still polling for other data changes using RTK Query?
Please note I can’t simply remove this unstable property (e.g., in the transformResponse
) because I need the value of this unstable property in other components.