Does anyone know if it's possible to implement Rea...
# javascript
b
Does anyone know if it's possible to implement React's
useState
hook in pure kotlin? Or does it rely on JS's
var
magic? Posted in #react
t
in pure Kotlin
What does it mean?
b
No usage of external declarations
t
Custom react hook?
b
No, completely reimplement useState in kotlin without using any react libs
t
Property delegate?
stdlib contains some implementations Also you can implement custom
b
Mail showstopper here is how you ensure you get the same value when calling it in functional component each render.
t
b
Yeah, but that uses rawSetState which is react external
Anyways, I think I got it in pure Kotlin
Copy code
typealias SetState<T> = (value: T) -> Unit

operator fun <T> Pair<T, SetState<T>>.getValue(thisRef: Any?, property: KProperty<*>): T {
  return first
}

operator fun <T> Pair<T, SetState<T>>.setValue(thisRef: Any?, property: KProperty<*>, value: T) {
  second(value)
}

private val store = mutableListOf<Any?>()
private var index = 0
fun <T> useState(initValue: T): Pair<T, SetState<T>> {
  @Suppress("UNCHECKED_CAST") 
  val currentState = (store[index] ?: initValue) as T
  val setState = fun(): SetState<T> {
    val currentIndex = index
    return fun(value:T) {
      store[currentIndex] = value
    }
  }()
  index++
  return currentState to setState
}

fun usageExample() {
  val (text, setText) = useState("none")
  val count by useState(0)
}
t
Mail showstopper here is how you ensure you get the same value when calling it in functional component each render.
You can use
provideDelegate
if you need common state for delegates
All states will be controlled by provider
b
Can't seem to find provideDelegate in IDE
t
Store - classic delegate provider
b
Yeah, don't think this would work as there's no owning object. useState needs to be able to be called in top-level fun
t
You are right, thisArg must be
Nothing?
for delegates
Store can be provided via constructor
Inner class delegate
b
Would you mind posting some code snippet?
t
A little bit later. Smartphone isn't good for code typing :)
b
Thanks. Anyways, just tested my solution and it works! (provided you reset index to 0 each render cycle
Copy code
import kotlin.reflect.*

typealias SetState<T> = (value: T) -> Unit

operator fun <T> Pair<T, SetState<T>>.getValue(thisRef: Any?, property: KProperty<*>): T {
  return first
}

operator fun <T> Pair<T, SetState<T>>.setValue(thisRef: Any?, property: KProperty<*>, value: T) {
  second(value)
}

private val store = mutableMapOf<Int, Any?>()
var index = 0
fun <T> useState(initValue: T): Pair<T, SetState<T>> {
  @Suppress("UNCHECKED_CAST")
  val currentState = (store[index] ?: initValue) as T
  store[index]= currentState
  
  val setState = fun(): SetState<T> {
    val currentIndex = index
    return fun(value: T) {
      store[currentIndex] = value
    }
  }()
  index++
  return currentState to setState
}
Interested to see yours when you get to it
t
Do you need to know if store changed?
Store.kt
b
Yep, I've pretty much done the same thing with differnet syntax. Good to know I'm on the right trach
@Hamza also the above
h
👍
t
Why not delegate? 1.
Pair
as result looks ugly in this case 2. Extensions on lambdas too You can encapsulate logic with delegate
get
+
set
encapsulation - classic delegate case
Copy code
// Now
val setState = fun(): SetState<T> {
    return fun(value: T) {
      store[currentIndex] = value
    }
  }()

// Expected
val setState: SetState<T> = {
    store[currentIndex] = it
}
b
Not decided yet. My initial thinking was to preserve classic usage
Copy code
val (state, setState) = useState(1)
You can still use it as
Copy code
val state by useState(1)
with my current solution
But i guess that's not as useful in kotlin
t
RStateDelegate supports both variants via
component
operators
b
Again, this is not for js code, but rather common code. So no js-only dependencies
t
Delegate doesn’t contain JS specific
Clear Kotlin
b
Yes, but it's useless by itself. Anyways my solution does the same without declaring the delegate