Skip to content
This repository has been archived by the owner on Jan 1, 2025. It is now read-only.

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Question: how to deal with data structures after decomposition into atomFamily? #905

Closed
digizen opened this issue Feb 28, 2021 · 7 comments
Labels
question Further information is requested

Comments

@digizen
Copy link

digizen commented Feb 28, 2021

Looking for guidance on the "correct" way to gather & iterate over data that's been decomposed into AtomFamily units.

Let's say I have an app that lets me draw shapes, and each shape's data is stored in an Atom, each atom being a part of an AtomFamily. I also have another Atom that has a list of the shape IDs so that I can iterate over the when doing the drawing. So far so good.

Now let's say I want to only display the blue rectangles. The color and shape is stored in the AtomFamily atoms, so the data is not immediately available.

The way my app works right now is that I have a data backing store (a JavaScript Map object) outside of the whole Recoil system. Every time I save a recoil atom I also push changes back into the backing store. Then, when I need to regenerate my "display list" I use that backing store.

My approach doesn't feel optimal, so I wanted to ask for your opinion of what a better approach should be. One possibility I came up with is to create a new list of shape IDs by "looking up" each atom, maybe inside a useRecoilCallback via the Snapshot property?

Is there a "correct" way of handling composite/complex data structures with recoil?

Thanks in advance for any guidance you can provide,
Greg

@mondaychen mondaychen added the question Further information is requested label Mar 3, 2021
@42shadow42
Copy link

42shadow42 commented Mar 14, 2021

I think you have the right idea using useRecoilCallback and the snapshot, here is a sandbox that shows it working, not sure if it scales though.

https://codesandbox.io/s/dazzling-fermat-ui6zy

@digizen
Copy link
Author

digizen commented Mar 16, 2021

Thank you very much, very helpful!

@drarmstr
Copy link
Contributor

If you're looking at synchronizing atoms with a backing store you may also want to consider the atom effects interface.

@wsmd
Copy link

wsmd commented Apr 23, 2021

Another way of achieving this could be possible by using a selector as it allows you access the values of all other atoms and atom families. The selector in this case returns a list of ids that conform to the selected filters:

const shapeIdsState = atom({ key: 'shapeIds', default: [] });
const shapeState = atomFamily({ key: 'shape', default: null });
const shapeFilterState = atom({ key: 'shapeFilter', default: null })
const colorFilterState = atom({ key: 'colorFilter', default: null })

const filteredIdsSelector = selector({
  key: "filteredIdsSelector",
  get({ get }) {
    const ids = get(shapeIdsState);
    const shapeFilter = get(shapeFilterState);
    const colorFilter = get(colorFilterState);
    if (!shapeFilter && !colorFilter) {
      return ids;
    }
    return ids.filter((id) => {
      const shape = get(shapeState(id))
      // filtering logic goes here... (omitted for brevity)
    });
  }
});

function Shapes() {
  const filteredIds = useRecoilValue(filteredIdsSelector);
  return (
    <>
      {filteredIds.map(id => (
        <Shape id={id} key={id} />
      ))}
    </>
  )
}

@42shadow42
Copy link

There's a known issue with loops in selectors being slow and halting the program. I believe that selector would trigger that case.

@wsmd
Copy link

wsmd commented Apr 23, 2021

Interesting! Looks like you're referring to #914 & #900. That's good to know. I'll keep that in mind!

I haven't had any issues with this yet, but maybe because i haven't used it with a very large data set.

@drarmstr
Copy link
Contributor

For ad-hoc usage to gather data from multiple atoms/selectors, there is also the waitForAll() util which can be used inline in a component directly to avoid making a new selector.

@facebookexperimental facebookexperimental locked and limited conversation to collaborators Apr 23, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

5 participants