Kotlin Js delegate property bug? Koltin 1.3.61

While using kotlin js (1.3.61) in conjunction with react I found some unexpected behavior. I have a state object that looks like this

data class PlotsState(var options: MutableMap<String, PlotData> = mutableMapOf(), var loading: Boolean = false) : RState {
    var date: String? by QueryParam()
    var selected: String? by QueryParam()
}

When I access like this

state = PlotsState()
state.date="test"

it works as expected. However, inside my render method it does not

attrs {
    value = state.date ?: none
    onChangeFunction = { event ->
        state.date = event.asHasValueElementOrNull()?.value ?: ""
        setState(state)
    }
}

“value = state.date ?: none” shows undefined and "state.date = " does not work as intended.

While debugging I noticed that before the assignment the state object looks like this

image

While after it looks like this

image

Date field is added rather than using the delegate property.
So it looks like that for some reason it is accessing the value by name rather than by mangled name. Also setting the @JsName annotation on the property doesn’t seem to change anything at all for delegate properties, name is still mangled.

I got it to work by wrapping the properties in a separate class

class QueryData {
    var date by  QueryParam()
    var selected by QueryParam()
}

data class PlotsState(var options: MutableMap<String, PlotData> = mutableMapOf(), var loading: Boolean = false, var queryData: QueryData = QueryData()) : RState

Not sure why this works vs the other solution. I tried to make the new wrapper class a data class also to see if the issue was tied to data classes but things still work fine that way. Maybe the problem is related to extending RState?

Your RState definition should be compatible with plane Javascript object which the state of RComponent actually is in runtime. That means you should use data classes with all properties defined in primary constructor since Kotlin does not mangle their names. And there is no reason to make them var since react documentation clearly states that you cannot directly modify state of a component, you should call setState instead.

Well, it’s not entirely true about mandatory data class usage. The point is, all enumerable properties of RState definition are copied to state object. So the delegated properties end up as delegate objects with mangled names in component’s state which is clearly not your intent.

So any way to use a data class and also have delegate properties? It appears those are not supported on constructors.

Yes. The vars are for state.someval=“new val” followed by setState(state). I know I can also use setState{} but the code I’m using wasn’t using it so I will likely update to that later.

Why would you want delegated properties in a data class? It is supposed to be a simple data storage with some autogenerated convenience methods. I’m not sure how delegated properties fit in here.

Don’t do this. React expects that state is immutable. You’ll get undefined behaviour changing state like that.