atomicobject / lenses

MIT License
57 stars 6 forks source link

Using lenses with a hash map #16

Closed mealeyst closed 2 years ago

mealeyst commented 2 years ago

Been loving the structure that lenses provide and we have been taking steps over at Daily Harvest to start leveraging this library to interact with our Redux state. For privacy reasons I can't post actual company code, but I was hoping to get some guidance with using lenses and more specifically Prisms when it comes to data that is in a hash map structure.

I am going to try my best to shown an example of what we are working with here:

To start we have our top level state:

{
  "users": {
    "data": {
      "odGeBUzJNS": {
        "f_name": "Jennifer",
        "l_name": "Lawrence",
        "age": 31,
        "profilePicture": "https://example.com/odGeBUzJNS.jpeg",
        "uuid": "odGeBUzJNS"
      },
      "8t7oCJlu2K": {
        "f_name": "James",
        "l_name": "Franco",
        "age": 43,
        "profilePicture": "https://example.com/8t7oCJlu2K.jpeg",
        "uuid": "8t7oCJlu2K"
      },
      "uLZNlm3oiI": {
        "f_name": "Tom",
        "l_name": "Holland",
        "age": 25,
        "profilePicture": "https://example.com/uLZNlm3oiI.jpeg",
        "uuid": "uLZNlm3oiI"
      }
    },
    "isLoading": false,
    "error": null
  },
  "films": {},
  "agencies": {}
}

I have been able to create lenses to get to the data that live immediately under users, the issue I was having was composing selectors that allowed for the selection of things like f_name, l_name, age, etc. I created a prism like so:

export const uuidPrism = <T extends keyof UsersKeyedByUuid>(key: T) => {
  return Prism.of<UsersState, UsersKeyedByUuid[T] | null>({
    get: (state) => data(state) && data(state)![key],
    set: (state, value) => 
      produce(state, (newState) => {
        if (newState.data && value)
          newState.data[key] = value;
      }),
  });
}

I was able to then access the user data by doing the following in my tests:

uuidPrism(uuid).get(state)

I just wasn't sure how to then compose other Lenses/Prisms from this. I saw the example in the tests of this library where we get the first index of an array and compose a new prism to gain access to the inner object of that array. Would it make sense to possibly export a function that sets the uuidPrism and returns the associated Lenses/Prisms? I was hoping to keep the nice and neat object structure that we have for some of our other states where we simply return an object of composed Lenses and Prisms. I just don't know if that is possible with the record hash map structure that I am working with.

mealeyst commented 2 years ago

So I actually figured out a solution to this issue, and I am going to try to post a solution to the method I found for others to poke around at and close this issue for now.