Skip to content

RoomsTable: Side effect (setCurrent) called inside useMemo violates React rendering contract #40589

Description

@SiddhiPandey08

Description

In apps/meteor/client/views/admin/rooms/RoomsTable.tsx, a state setter (setCurrent(0)) is called inside a useMemo callback to reset pagination when the search text changes. Calling state setters inside useMemo is a side effect during render, which React explicitly prohibits — memos must be pure computations.

Affected File

apps/meteor/client/views/admin/rooms/RoomsTable.tsx

Problematic Code

const query = useDebouncedValue(
    useMemo(() => {
        if (searchText !== prevRoomFilterText.current) {
            setCurrent(0); //  side effect inside useMemo
        }
        return { ... };
    }, [searchText, sortBy, ...]),
    500,
);

Why It's Wrong

  • useMemo must be a pure computation with no side effects
  • Calling setCurrent here triggers a state update during render
  • In React Strict Mode, useMemo can be invoked multiple times, potentially firing setCurrent(0) more than once
  • prevRoomFilterText is updated in a useEffect which runs after render, creating a timing window where the condition fires incorrectly on intermediate re-renders

Proposed Fix

Move the pagination reset into a useEffect watching searchText, and remove the side effect from the memo:

useEffect(() => {
    setCurrent(0);
    prevRoomFilterText.current = searchText;
}, [searchText, setCurrent]);

And simplify the memo to a pure computation:

const query = useDebouncedValue(
    useMemo(() => ({
        filter: searchText || '',
        sort: `{ "${sortBy}": ${sortDirection === 'asc' ? 1 : -1} }`,
        count: itemsPerPage,
        offset: current,
        types: ...,
    }), [searchText, sortBy, sortDirection, itemsPerPage, current, roomFilters.types]),
    500,
);

Notes

Verified on develop branch. Checked UsersTable.tsx and ChannelsTable.tsx — neither has this pattern. Issue is isolated to RoomsTable.tsx.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions