MVICore icon indicating copy to clipboard operation
MVICore copied to clipboard

Private state representation for feature

Open tieskedh opened this issue 5 years ago • 3 comments

I have a NavFeature which handles routes. NavWish(path: String) goes in and NavState(module: String, args : ...) goes out. All my code depends on Store<NavWish, NavState>. Now I want to use a stack with NavStates, but I don't want the rest of my code to know that I'm using a Stack.

What is the best way to expose a Store-interface without the stack, but use the stack interrnally?

tieskedh avatar Dec 11 '19 18:12 tieskedh

Hi @tieskedh Currently, feature does not support private states, but you can hide it using binder.

// state in feature
data class State(
    val stack: List<String>
)

// somewhere outside
binder.bind(feature to navigator using StateToNavigator)

object StateToNavigator : (State) -> NavState {
    override fun invoke(state: State): NavState = NavState(state.stack.last())
}

ShikaSD avatar Dec 12 '19 11:12 ShikaSD

But in that case, the class passed around doesn't implement Store anymore... At this moment I'm using the following code:

class PublicNavigationFeature : Store<NavigationWish, NavigationState>{
    private val subject  = BehaviorSubject.create<NavigationStackState>()
    val navigationStackFeature = NavigationStackFeature().apply {
        subscribe(subject)
    }.wrapWithMiddleware()

    override val state: NavigationState get() = subject.value!!.navigationState.last()

    override fun accept(wish: NavigationWish) = navigationStackFeature.accept(wish)

    override fun subscribe(observer: Observer<in NavigationState>) {
        subject.map { 
            it.navigationState.lastOrNull() ?: NavigationState("close", "close") 
        }.subscribe(observer)
    }
}

tieskedh avatar Dec 13 '19 12:12 tieskedh

If you subscribe to state update directly, it is possible to use abstraction similar to yours (although it is better to call it PublicNavigationStore as it is not a feature anymore).

We encourage using Binder nonetheless, as it will take care of lifecycle management, so nothing will be leaked. You can pass NavigationStackFeature around (it implements store) and use transformer to access required fields. As the state is not mutable anyway, you won't be able to update it from outside, so the stack data will be consistent.

ShikaSD avatar Dec 16 '19 14:12 ShikaSD