2

I have the following code:

import { atom, atomFamily, selector, selectorFamily } from 'recoil';

import { VIDEO_STATUSES } from '../../constants';

export const videosDict = atomFamily({
  key: 'videos',
  default: {},
});

export const videoIds = atom({
  key: 'videoIds',
  default: [],
});

export const videosFilteredState = atom({
  key: 'videosFilteredState',
  default: VIDEO_STATUSES.SCRAPED.value,
});

export const videosFiltered = selector({
  key: 'videosFiltered',
  get: ({ get }) => {
    const filter = get(videosFilteredState);
    const ids = get(videoIds);

    switch (filter) {
      case VIDEO_STATUSES.SCRAPED.value:
        return ids.filter((id) =>
          [
            VIDEO_STATUSES.SCRAPED.value,
            VIDEO_STATUSES.APPROVED.value,
          ].includes(get(videosDict(id)).status),
        );
      case VIDEO_STATUSES.UPLOADED.value:
        return ids.filter(
          (id) => get(videosDict(id)).status === VIDEO_STATUSES.UPLOADED.value,
        );
      case VIDEO_STATUSES.HIDDEN.value:
        return ids.filter(
          (id) => get(videosDict(id)).status === VIDEO_STATUSES.HIDDEN.value,
        );
      default:
        return ids;
    }
  },
});

export const videosSelector = selectorFamily({
  key: 'videosSelector',
  get:
    (id) =>
    ({ get }) =>
      get(videosDict(id)),
  set:
    (id) =>
    ({ set }, data) =>
      set(videosDict(id), data),
});

This is working as expected, the list of ID's is used in the parent list component where it will use a .map and render children item components based on the list ID's

Within the item components, it will use the videosSelector to grab the actual data so that I can have a local state.

When I click a button within the item, it re-renders the entire list (shown through React Dev Tools highlighting).

If I hack it up and just use videoIds instead of videosFiltered, it doesn't re-render the whole list.

In the list component, I get the filtered videos like so:

const videos = useRecoilValue(videosFiltered);
...
return <Grid container>
        {videos.map((id) => (
          <Video key={id} id={id} />
        ))}
      </Grid>

Why does the list re-render when I'm updating the state of a single member of the atomFamily?

PGT
  • 1,468
  • 20
  • 34
  • The code you've provided can't be debugged because it isn't a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). If you can modify the code in your question such that others can actually run it and debug it, I'm confident that you'll get an answer. [Here's an example](https://stackoverflow.com/a/72134673/438273) that you can use as a template if needed. – jsejcksn Jul 03 '22 at 19:12

0 Answers0