Mobx observable only get updated if i log it

99 views Asked by At

I have a hook that uses an observable which is a map - peripheralStore.connectedDevices. this map consists with values which are also observables - Sensor

The hook updates when peripheralStore.connectedDevices changes, but the values themself aren’t.

Funny thing about it is that once i log the entire map, the hook get re-renders with every changes in the the map's values

My Custom Hook:

export default function useSensor(): UseSensorObj {
  const { peripheralStore } = useStore()
  const devices = peripheralStore.connectedDevices
  const isConnected: boolean = !_.isEmpty(devices)

  const value = devices?.values().next()
  //console.log(`log: ${JSON.stringify(devices)}`)
  const batteryLevel = value?.value?.battery

  return { devices, batteryLevel, isConnected }
}

here is how i updated the map:

 class PeripheralStore implements IPeripheralStore {

   constructor(...) {
     makeAutoObservable(this, {}, { autoBind: true })
     ...
   }

   private async initSensor(sensor: ISensor) {
     await runInAction(async () => {
       sensor.init()
       this.connectedDevices.set(sensor.peripheral.id, sensor)
     })
   }
 ...
}

and here is how i update the object's data:

 class Sensor implements ISensor {
   constructor(...) {
     makeAutoObservable(this, {}, { autoBind: true })
     ...
   }
   this.monitorCharacteristic(...) => {
    runInAction(() => {
      const battery = decodeByteArrival[17]

      if (this.battery !== battery) {
        this.battery = battery
      }
    ...
    })
  }
  ...
}
1

There are 1 answers

3
Danila On

You probably need to reread this chapter of the docs https://mobx.js.org/understanding-reactivity.html#understanding-reactivity

MobX reacts to any existing observable property that is read during the execution of a tracked function.

"reading" is dereferencing an object's property, which can be done through "dotting into" it (eg. user.name) or using the bracket notation (eg. user['name'], todos[3]) or destructuring (eg. const {name} = user).

When you do JSON.stringify it basically reads every property of your object/array or whatever, so this hook will rerender on any property change. And when you don't have JSON.stringify you only read top level property (array/object itself) so the hook only reacts to that property change, not inner ones.