https://kotlinlang.org logo
#javascript
Title
# javascript
h

Hildebrandt Tobias

11/29/2023, 11:22 PM
I am currently fiddling with KotlinJS and React. I wanted to use the State and Context functionality, but since I am unexperienced in JS and React native I don't understand how it's supposed to work in KotlinJS. This is the tutorial I tried to follow: https://www.basefactor.com/global-state-with-react I cannot wrap my head around how I can use the dispatch and reducer to modifly the context. What I tried:
Copy code
val authContext = createContext<AuthJWT?>(null)
val authDispatch = createContext<Unit>()
val authReducer: Reducer<AuthJWT?, AuthJWT> = { state, action ->
    action
}

object AuthStore {
    fun setToken(jwtToken: AuthJWT) {
        // ??
    }
}
I slowly make progress (I think). Currently looking at this and wondering how I implement the nested children like in the example here: https://react.dev/learn/scaling-up-with-reducer-and-context
Copy code
val authContext = createContext<AuthJWT?>(null)
val authDispatch = createContext<Dispatch<AuthJWT>>()
val authReducerTask: Reducer<AuthJWT?, AuthJWT> = { state, action ->
    action
}
val authReducer = useReducer(authReducerTask, null)

val AuthenticationProvider = FC<Props> {
    authReducer.let {(state, dispatch) ->
        authContext.Provider(value = state) {
            authDispatch.Provider(value = dispatch) {
                // children() ?
            }
        }
    }
}
I am slowly getting towards the pulling my hair out stage. I reduced my example to a String:
Copy code
val authContext = createContext<String?>(null)
val authDispatch = createContext<Dispatch<String>>()
val authReducerTask: Reducer<String?, String> = { state, action ->
    println("Reducer called with Action $action")
    action
}
The entrypoint App.kt is essentially just:
Copy code
val App = FC<Props> {
    val authReducer = useReducer(authReducerTask, null)
    StrictMode {
        authReducer.let {(state, dispatch) ->
            authContext.Provider(value = state) {
                authDispatch.Provider(value = dispatch) {
                    CssBaseline()
                    RouterProvider {
                        router = appRouter
                    }
                }
            }
        }
    }
}
The Main.kt
Copy code
val Main = FC<Props> {
    val token = useContext(authContext)
    println("Main context: ${authContext.hashCode()}")
    println("Main token: $token")
}
The Login.kt
Copy code
val LoginView = FC<Props> {
    val token = useContext(authContext)
    println("LoginView context: ${authContext.hashCode()}")
    println("LoginView Token: $token")
    location.href = "${environment.SERVER_URL}/login/callback"
}
And the LoginCallback.kt
Copy code
val LoginCallback = FC<Props> {
    val token = useContext(authContext)
    val dispatch = useContext(authDispatch)
    println("LoginCallback context: ${authContext.hashCode()}")
    println("LoginCallback Token: $token")
    println("LoginCallback Dispatch: $dispatch")
    dispatch?.let {
        println("Dispatching")
        it("NEW TOKEN")
    }
    location.href = environment.SERVER_URL // back to main.
}
So when I visit
/login
he does a roundtrip to
/login/callback
and then finally sits at
/
. But when I look at the Output then the String is not written and always null. Console:
Copy code
LoginView context: -208293842
LoginView Token: null
LoginView context: -208293842
LoginView Token: null
LoginCallback context: -1122324025
LoginCallback Token: null
LoginCallback Dispatch: function () { [native code] }
Dispatching
Reducer called with Action NEW TOKEN
LoginCallback context: -1122324025
LoginCallback Token: NEW TOKEN
LoginCallback Dispatch: function () { [native code] }
Dispatching
LoginCallback context: -1122324025
LoginCallback Token: NEW TOKEN
LoginCallback Dispatch: function () { [native code] }
Dispatching
Reducer called with Action NEW TOKEN
Main context: 1918903185
Main token: null
Main context: 1918903185
Main token: null
a

Artem Kobzar

12/01/2023, 9:18 AM
So, the problem is, that you are navigating throw the browser api, so, your web app will be reloaded and the state will be reset. To fix it, you shouldn't directly manipulate with the location href, but use some router, like react-router, that will not directly reload your page and will keep the updated state. https://github.com/JetBrains/kotlin-wrappers/blob/master/kotlin-react-router-dom
h

Hildebrandt Tobias

12/02/2023, 2:39 PM
Hey, thank you very much for your input. I will check this out this evening. I used
href
because on a SO answer there was a snippet on why to always use
href
. Thanks!
Hey, thanks again for your input. It worked. Just a comprehension question. If the context is lost/discarded/changes with a manual reload or navigation by direkt URL change. How would I go about retrieving the context again? I know redux exists, but I wanted to try to avoid it for now to practice more. Is this where I use
useLocalStorage
to retrieve relevant data and rebuild the context again?
4 Views