ReactiveMap

I am having an issue with reactive map - i think i know why it's happening but i have no idea how to fix it. I have the below code
Setting up the Store (static map just for testing)
const tempCameraComponents: ReactiveMap<string, ICamera> = new ReactiveMap<string, ICamera>(
[
['left_eye_tracker', {
status: CameraStatus.LOADING,
type: CameraType.WIRELESS,
address: '192.168.0.204',
activeCameraSection: 'Left Eye',
}],
['right_eye_tracker', {
status: CameraStatus.LOADING,
type: CameraType.WIRELESS,
address: '192.168.0.232',
activeCameraSection: 'Right Eye',
}],

]
)

export const defaultState: IMdnsStore = {
connectedUser: '',
restClient: '',
camerasMap: tempCameraComponents
}

const [state, setState] = createStore<IMdnsStore>(defaultState)
export const cameras = createMemo(() => mdnsState().camerasMap)
const tempCameraComponents: ReactiveMap<string, ICamera> = new ReactiveMap<string, ICamera>(
[
['left_eye_tracker', {
status: CameraStatus.LOADING,
type: CameraType.WIRELESS,
address: '192.168.0.204',
activeCameraSection: 'Left Eye',
}],
['right_eye_tracker', {
status: CameraStatus.LOADING,
type: CameraType.WIRELESS,
address: '192.168.0.232',
activeCameraSection: 'Right Eye',
}],

]
)

export const defaultState: IMdnsStore = {
connectedUser: '',
restClient: '',
camerasMap: tempCameraComponents
}

const [state, setState] = createStore<IMdnsStore>(defaultState)
export const cameras = createMemo(() => mdnsState().camerasMap)
I am trying to render it as such:
const CameraHandler = () => {
const _cameras = cameras()
console.log('cameras:', _cameras.size)
return (
<Show
when={_cameras.size > 0}
fallback={
<div class="flex flex-col items-center justify-center w-full h-full">
<Text size="2xl" class="font-bold tracking-[0.10rem] text-[white]">
No cameras found
</Text>
</div>
}>
<For each={Array.from({ length: _cameras.size })}>
{() => {
createEffect(() => console.log('increment:', _cameras.values().next().value))
return <Camera {...(_cameras.values().next().value as ICamera)} />
}}
</For>
</Show>
)
}
const CameraHandler = () => {
const _cameras = cameras()
console.log('cameras:', _cameras.size)
return (
<Show
when={_cameras.size > 0}
fallback={
<div class="flex flex-col items-center justify-center w-full h-full">
<Text size="2xl" class="font-bold tracking-[0.10rem] text-[white]">
No cameras found
</Text>
</div>
}>
<For each={Array.from({ length: _cameras.size })}>
{() => {
createEffect(() => console.log('increment:', _cameras.values().next().value))
return <Camera {...(_cameras.values().next().value as ICamera)} />
}}
</For>
</Show>
)
}
Now, it renders two components - however it renders two of the first mapped object. Which i don't understand at all. What am i doing wrong?
16 Replies
thetarnav
thetarnav•17mo ago
if your keys are strings, why not use a store?
DaOfficialWizard🧙
not sure i understand i thought i was creating the store correctly 😅
thetarnav
thetarnav•17mo ago
I mean instead of ReactiveMap easier to manage 1 api then 2 also this would probably work better
<For each={cameras.keys()}>
{(key) => <Camera {cameras.get(key)} />}
</For>
<For each={cameras.keys()}>
{(key) => <Camera {cameras.get(key)} />}
</For>
DaOfficialWizard🧙
i thought using the map was nice because i can lookup a camera based on the device name later on. Just a get() and set() api to retrieve or add camera's
thetarnav
thetarnav•17mo ago
you can have the same with store if keys are strings
DaOfficialWizard🧙
i am totally new - i am not really sure how i would do that. I am from c++ - maps are in my blood xD forgive my ignorance xD isn't that just an array of objects? or object of objects
thetarnav
thetarnav•17mo ago
yeah no problem they are common use in normal js too but stores natively support only plain objects and arrays you can import 3rd party lib for reactive maps, but you may just be adding complexity needlessly and thats coming from a person that created the solid-primitives/map package 🤣 😅
DaOfficialWizard🧙
i understand 🙂 thanks for the heads up I am going to switch this doesn't work This get's close, but throws an undefined error
<For each={_cameras.keys().next().value}>
{(key) => <Camera {...(_cameras.get(key) as ICamera)} />}
</For>
<For each={_cameras.keys().next().value}>
{(key) => <Camera {...(_cameras.get(key) as ICamera)} />}
</For>
it comes off of the iterable that keys() returns
thetarnav
thetarnav•17mo ago
how about this
<For each={Array.from(cameras.keys())}>
{(key) => <Camera {cameras.get(key)} />}
</For>
<For each={Array.from(cameras.keys())}>
{(key) => <Camera {cameras.get(key)} />}
</For>
DaOfficialWizard🧙
no, Property keys does not exist on type Accessor<ReactiveMap> ah, its key nope i was wrong
thetarnav
thetarnav•17mo ago
cameras is probably meant to be _cameras -> value not a signal
DaOfficialWizard🧙
liquid is just gone xD lol
thetarnav
thetarnav•17mo ago
I mean it's in his name
DaOfficialWizard🧙
yeah, this works perfect
<For each={Array.from(_cameras.keys())}>
{(key) => <Camera {...(_cameras.get(key) as ICamera)} />}
</For>
<For each={Array.from(_cameras.keys())}>
{(key) => <Camera {...(_cameras.get(key) as ICamera)} />}
</For>
but i agree - i should just use an object of objects thank you both for the kick in the right direction
thetarnav
thetarnav•17mo ago
this might be useful for you then https://github.com/solidjs/solid/issues/1300 if you want to have similar interface but not necessary
GitHub
Creating a store from another breaks read-write segregation · Issue...
Describe the bug You can easily create a store from a &quot;read-only&quot; proxy returned by another, gaining write access to the state and causing reactive updates to the original store. ...
DaOfficialWizard🧙
small update - migrated the camera component away from map - purrs like a kitten now 🙂 thanks ya'll