State Management — KMP
State as a Data Class
In the KMP / Decompose path, state is a plain data class — no marker interface required.
data class HomeState(
val title: String = "",
val isLoading: Boolean = false,
)
Holding and Updating State
BaseComponent provides componentState: MutableStateFlow<VS> to hold the component's state.
Update state by replacing the value directly:
componentState.value = componentState.value.copy(title = "new")
Or use the update helper from app.futured.arkitekt.decompose.ext:
update(componentState) { copy(title = "new") }
Exposing State
Expose state to the UI as a read-only StateFlow:
class HomeComponent(
componentContext: AppComponentContext,
) : BaseComponent<HomeState, HomeUiEvent>(componentContext, HomeState()) {
val state: StateFlow<HomeState> = componentState
}
asStateFlow Helper
BaseComponent provides an asStateFlow() extension on Flow<VS> that converts a Flow to a StateFlow within the component's coroutine scope. This is useful when you want to derive state from another flow:
val derivedState: StateFlow<DerivedState> = someFlow
.map { DerivedState(it) }
.asStateFlow(SharingStarted.WhileSubscribed(5_000))
Observing State in Compose
@Composable
fun HomeScreen(component: HomeComponent) {
val state by component.state.collectAsState()
if (state.isLoading) {
CircularProgressIndicator()
} else {
Text(state.title)
}
}
Value / Flow Conversions
Arkitekt provides utility extensions for bridging Decompose Value and Kotlin Coroutines StateFlow / Flow APIs.
Value<T>.asStateFlow()
Converts a Decompose Value to a Kotlin StateFlow:
val state: StateFlow<HomeState> = decomposeValue.asStateFlow()
Flow<T>.collectAsValue(initial, coroutineScope)
Converts a Kotlin Flow to a Decompose Value:
val decomposeValue: Value<HomeState> = stateFlow.collectAsValue(
initial = HomeState(),
coroutineScope = componentCoroutineScope,
)