reactjstypescriptmobxdestructuringobject-destructuring

Unable to set properties of undefined when destructuring a functional property


The issue I'm having isn't one that needs fixing so to speak more so I'm curious as to why this functionality changes. This code is in Typescript and I'm using Mobx as well.

I have a state called GlobalPageState with a property selectedTab and a function to set this property called setSelectedTab

export default GlobalPageState extends State {
 @observable
 public selectedTab = string;

 @action
 public setSelectedTab(selectedTab: PageTab) {
  this.selectedTab = selectedTab;
 }
}

in my react component, I've destructured these properties and referenced them as such:

const { selectedTab, setSelectedTab } = GlobalPageState

const onTabSelect = (newTab: string) => {
 setSelectedTab(newTab)
} 

This gives me the error that I can't set the properties of undefined. However, this works:

const { selectedTab } = GlobalPageState

const onTabSelect = (newTab: string) => {
 GlobalPageState.setSelectedTab(newTab)
}

Why would this be the case, assuming everything else remains the same? Does destructuring the function call in this case somehow change its functionality i.e. referencing? Not shown are a lot of other functions and properties on GlobalPageState that is being used, and those all work fine when destructured in this way so I'm unsure why this call would be different. Thanks!


Solution

  • Basically you just need to read how this works in Javascript https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

    tl;dr: your function is losing context when you assign it to the variable and then call without dot, like class.method()

    Regarding to MobX you can also use @action.bound although I would recommend sticking to arrow functions because it is more "native" JS way of doing thing. Also it is usually better to define all public class methods (actions) as arrow functions, that way you don't need to worry if you destructure them or not, you can call them either way.