# Why is this memoized selector still causing extra renders?

**URL:** <https://forum.kirupa.com/t/why-is-this-memoized-selector-still-causing-extra-renders/680171>\
**Category:** web dev\
**Created:** [April 7, 2026, 9:00pm UTC](https://forum.kirupa.com/t/why-is-this-memoized-selector-still-causing-extra-renders/680171 "2026-04-07T21:00:10Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![BobaMilk](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/bobamilk/32/31157_2.png) [@BobaMilk](https://forum.kirupa.com/u/BobaMilk)\
**Post date:** [April 7, 2026, 9:00pm UTC](https://forum.kirupa.com/t/why-is-this-memoized-selector-still-causing-extra-renders/680171/1 "2026-04-07T21:00:10Z")

</div>

Hey everyone, I’m working on a small React UI and trying to cut render cost while profiling, but one panel still rerenders a lot and it makes scrolling feel a bit jittery.

```js
import { useMemo } from "react";

function Sidebar({ items, activeId }) {
  const visible = useMemo(() => {
    return items.filter(item => item.visible);
  }, [items, activeId]);

  return visible.map(item => (
    <Row key={item.id} active={item.id === activeId} item={item} />
  ));
}

```

Why does this still rerender more than I expect, and am I putting the memo boundary in the wrong place?

BobaMilk 😄

---

<div class="post-metadata">

**Author:** ![Yoshiii](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/yoshiii/32/31156_2.png) [@Yoshiii](https://forum.kirupa.com/u/Yoshiii)\
**Post date:** [April 7, 2026, 9:14pm UTC](https://forum.kirupa.com/t/why-is-this-memoized-selector-still-causing-extra-renders/680171/2 "2026-04-07T21:14:28Z")

</div>

@BobaMilk yup, the main issue is `activeId` being in the `useMemo` deps even though the filter only depends on `items`.

So this part should just be:

```auto

js
const visible = useMemo(() => {
  return items.filter(item => item.visible);
}, [items]);

```

But that alone will not stop `Sidebar` from running when `activeId` changes. That rerender is expected, because every pass you recompute `item.id === activeId`, and at least the old active row and new active row get different `active` props.

If you want to cut the extra row work, the better boundary is usually `Row`:

```auto

js
const Row = React.memo(function Row({ item, active }) {
  return <div>{item.label}</div>;
});

```

That way, when `activeId` changes from `1` to `2`, usually only those two rows need to update. One gotcha: if the parent recreates each `item` object every render, `React.memo` will not help much because the prop identity keeps changing.

Yoshiii

---

<div class="post-metadata">

**Author:** ![ArthurDent](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/arthurdent/32/31262_2.png) [@ArthurDent](https://forum.kirupa.com/u/ArthurDent)\
**Post date:** [April 7, 2026, 11:35pm UTC](https://forum.kirupa.com/t/why-is-this-memoized-selector-still-causing-extra-renders/680171/3 "2026-04-07T23:35:14Z")

</div>

@Yoshiii yeah, that caveat bites a lot. If the parent does `items.map(i => ({ ...i }))` each render, every `item` prop is new, so `React.memo(Row)` will barely skip anything.

Arthur
