What is the best way to dynamically update atoms that were created from an array and are stored at a unique index? Let me give the scenario I am working with for more context.
I am building an app that has a video call state. A video call can have n participants. Participants each have their own state as well as a global call state. We are using a third party service (dailyco) to manage the video/audio features of our app.
Through the dailyco api we get a list of participants as well as a way to subscribe to updates to said participants. My use case with recoil is as follows:
Create a unique atom for each participant that contains their state:
const participantBySessionId = memoize(id =>
atom<undefined | Participant>({
key: `participant-${id}`,
default: undefined,
})
)
Then in a functional component I am listening for updates to a participant from dailyco and then calling a handler function (where my question comes up):
const App: React.FC = () => {
...
const handleNewParticipantState = (sessionId) => {
// This is where my question comes up.
// How do I in this scenario dynamically update the atom at `participant-{sessionId}`
}
...
}
I have a solution that works to update a participant dynamically with selectors. But my solution (found below) doesn't feel like the right way... at least typescript complains when I don't set a get function in a selector, so using a selector to only update feels wrong:
const updateParticipant = selector({
key: "updateParticipant",
get: () => null,
set: (
{ set, get }: any,
{ action, participant }: { action: string; participant: Participant }
) => {
const participantAtom = participantBySessionId(participant.session_id)
set(participantAtom, participant)
},
})
I read through atomFamily, as that felt like it would be the solution, but I can't find a way to dynamically update an atom in the react lifecycle.
Anyhow, I could be totally missing something obvious in the docs. It may also be that the answer for this is that recoil may not be the right tool for my scenario. Thanks for taking the time to read this and I hope it made sense. Happy to clarify more if I left some things out.
Hi @vandercloak,
I think the easiest way to solve this is to create an atom family for participantBySessionId, and then in your component create a callback via useRecoilCallback which will roughly do: {set, get} => (id, action, participant) => get(participantBySessionId(id)) ... set(...)
Then when your handler is called it calls the callback you defined and sets the atom.
@Shmew I knew there was probably just something that I was missing in the docs... This answers my question fully. Thank you!
Most helpful comment
@Shmew I knew there was probably just something that I was missing in the docs... This answers my question fully. Thank you!