I'm new to Jetpack Compose and I'm facing an issue with implementing a button click. My scenario is as follows: I need to call an API when a button is clicked and update the UI once the response is received. While the API call is happening, I need to show a loader. However, I'm encountering the error "@Composable invocations can only happen from the context of a @Composable function." Below is a screenshot of my issue.
Any help would be deeply appreciated. Thanks in advance
if you check Button component document you will see onClick parameter is not allow composable lamda like onClick: @Composable () -> Unit
use a mutableState variable for show loading bar:
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
var loading: Boolean by remember{ mutableStateOf(false) }
Button(
enabled = enabled,
modifier = Modifier.fillMaxWidth(),
onClick = { if (!loading) onClick() },
colors = colors
) {
Row(
Modifier,
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
if (loading) {
CircularProgressIndicator(
color = colors.contentColor,
modifier = Modifier
.size(30.dp)
.progressSemantics()
)
} else {
Text(
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
text = text, // write your text
maxLines = 1
)
}
}
My advice create a function for it for Example:
fun PrimaryButton(
modifier: Modifier = Modifier,
loadingSize: Dp = 32.dp,
enabled: Boolean = true,
loading: Boolean = false,
colors: ButtonColors = ButtonDefaults.buttonColors().copy(
contentColor = Colors.White,
disabledContainerColor = Color.Gray,
containerColor = Color.Blue,
disabledContentColor = Color.White
),
text: String,
onClick: () -> Unit,
) {
Button(
enabled = enabled,
modifier = Modifier
.fillMaxWidth()
.then(modifier),
onClick = {
if (!loading)
onClick()
},
colors = colors
) {
Row(
Modifier,
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
if (loading) {
CircularProgressIndicator(
color = colors.contentColor,
modifier = Modifier
.size(loadingSize)
.progressSemantics()
)
} else {
Text(
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
text = text,
maxLines = 1
)
}
}
}
}
@Preview
@Composable
fun PrimaryButtonPreview() {
PrimaryButton(modifier = Modifier, text = "Button") {}
}