Hello everyone. I am with issues in recomposition ...
# compose
f
Hello everyone. I am with issues in recomposition when a variable has two truth of source, please more details in the thread.
Copy code
val state by component.states.collectAsState()

SliderProgress(
     value = state.velocity.toInt(),
     onFunctionClicked = component::onVelocityChanged,
)
Copy code
@Composable
internal fun SliderProgress(
    value: Int,
    onFunctionClicked: (Int) -> Unit,
) {
    var sliderPosition by remember { mutableStateOf(value.toFloat()) }

    Slider(
        value = sliderPosition,
        valueRange = 1f..50f,
        onValueChange = { sliderPosition = it },
        onValueChangeFinished = { onFunctionClicked(sliderPosition.toInt()) },
    )
}
When state is updated in the first time, the Slider is recomposed. When onValueChange is called the Slider is recomposed as well. But when state is updated after the slider is not recomposed anymore.
I changed a little the code above but the issue is present yet
Copy code
val state by component.states.collectAsState()
var sliderValue by remember { mutableStateOf(state.velocity.toFloat()) }

SliderProgress(
    value = sliderValue,
    onValueChange = { value -> sliderValue = value },
    onValueChangeFinished = component::onVelocityChanged,
)

@Composable
internal fun SliderProgress(
    value: Float,
    onValueChange: (Float) -> Unit,
    onValueChangeFinished: (Int) -> Unit,
) {
    Slider(
        value = value,
        valueRange = 1f..50f,
        onValueChange = { onValueChange(it) },
        onValueChangeFinished = { onValueChangeFinished(value.toInt()) },
    )
}
Can anyone give me an idea please??
s
sliderValue
is only evaluated once because it's wrapped in
remember
. how about:
Copy code
var sliderValue by remember { mutableStateOf(0) }
val state by component.states.collectAsState()
sliderValue = state.velocity.toFloat()
....
But I think the most obvious answer is don't have 2 sources of truth
f
your suggestion did not work, because when onValueChange is called the sliderValue is assignment with the value of
state.velocity.toFloat()
again
s
I'm sure there's a better way to do this, I'm still new to Compose, but maybe
Copy code
var sliderValue by remember { mutableStateOf(0) }
val state by component.states.collectAsState()
LaunchedEffect(state.velocity) { sliderValue = state.velocity.toFloat() }
Also, I'll stress again - consider making
state
your single source of truth. Maybe have state.localVelocity vs state.savedVelocity and forward both
onValueChange
and
onValueChangeFinished
to your component
f
Why did you call LaunchedEffect here???
s
Because it'll happen only once per unique value of
state.velocity
, which is what you want
f
ok, I understood now. I will try you suggestion later. I removed all "remember" calls and passed the velocity from viewmodel directly for the Slider
👏 1
worked fine
Copy code
val state by component.states.collectAsState()

SliderProgress(
    value = state.velocity.toFloat(),
    onValueChange = component::onVelocityChanged,
    onValueChangeFinished = component::onVelocityChangeFinished,
)

@Composable
internal fun SliderProgress(
    value: Float,
    onValueChange: (Float) -> Unit,
    onValueChangeFinished: () -> Unit,
) {
    Slider(
        value = value,
        valueRange = 1f..50f,
        onValueChange = { onValueChange(it) },
        onValueChangeFinished = { onValueChangeFinished() },
    )
}