Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Private state representation for feature #119

Open
tieskedh opened this issue Dec 11, 2019 · 3 comments
Open

Private state representation for feature #119

tieskedh opened this issue Dec 11, 2019 · 3 comments

Comments

@tieskedh
Copy link

tieskedh commented Dec 11, 2019

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?

@ShikaSD ShikaSD changed the title store mapper Private state representation for feature Dec 12, 2019
@ShikaSD
Copy link
Contributor

ShikaSD commented Dec 12, 2019

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())
}

@tieskedh
Copy link
Author

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)
    }
}

@ShikaSD
Copy link
Contributor

ShikaSD commented Dec 16, 2019

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants