i can't invoke the composable function inside of b...
# compose
p
i can't invoke the composable function inside of button onclick.and, I getting this error '@Composable invocations can only happen from the context of a @Composable function'
s
What do you expect to happen when you call a composable function as a result of a click happening?
p
I call the Login API using coroutinescope. if it’s success move to the home screen and if it’s failure throw the error.
s
Okay, so what composable function are you really calling in there then? Are you doing this?
Copy code
clickable {
  rememberCoroutineScope().launch { ... your stuff here }
}
If yes, just do this instead
Copy code
val coroutineScope = rememberCoroutineScope()
Button(
  onClick { 
    coroutineScope.launch { ... }
  }
)
p
yeah, i'm already using this way.
s
You need to be able to call a composable function from inside a composable context, so that it’s stored properly across compositions. If you just made a new coroutine scope inside the lambda each time it was called it’d get lost each time and you’d need to call that lambda
p
Copy code
@Composable
fun LoginScreen(navController: NavController){
    val context = LocalContext.current
    var username = remember {
        mutableStateOf("")
    }
    var password = remember {
        mutableStateOf("")
    }

    var isClicked = remember {
        mutableStateOf(false)
    }
    Column(modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally) {


        Text(
            modifier = Modifier.padding(10.dp),
            text = "Welcome to Login",
            color = Color.Black
        )
        Spacer(modifier = Modifier.height(10.dp))
        OutlinedTextField(
            value = username.value,
            onValueChange = { username.value = it},
            label = { Text("UserName") }
        )
        Spacer(modifier = Modifier.height(16.dp))
        OutlinedTextField(
            value = password.value,
            onValueChange = { password.value = it},
            label = { Text("PassWord")}
        )
        Spacer(modifier = Modifier.height(16.dp))
        Button(
            onClick = { isClicked = true }) {
            Text("Login")
        }
        if (isClicked){
            if (username.value.isNotEmpty()){
                Toast.makeText(context, "Please Enter Username", Toast.LENGTH_SHORT).show()
            }else if (password.value.isNotEmpty()){
                Toast.makeText(context, "Please Enter Password", Toast.LENGTH_SHORT).show()
            }else{
                    login()
            }
        }
    }
}
@Composable
fun login() {
    val context = LocalContext.current
    val scope = rememberCoroutineScope()
    var loginCred by remember {
        mutableStateOf(emptyList<LoginDataItem>())
    }
val navController = rememberNavController()
    LaunchedEffect(key1 = true ){
        scope.runCatching {
            LoginUrl().execute("admin","Aurolab")
        }.onSuccess{ loginCred ->
            navController.navigate("HomeScreen")
            Toast.makeText(context, "Login Successfully", Toast.LENGTH_SHORT).show()
        }.onFailure {
            Toast.makeText(context, "Error: ${it.message}", Toast.LENGTH_SHORT).show()

        }
    }
}
this is my code.
s
Which part is it that doesn’t work from all this?
p
now, am getting this error "The boolean literal does not conform to the expected type MutableState<Boolean>'
from here,
Copy code
Button(
            onClick = { isClicked = true }) {
            Text("Login")
        }
        if (isClicked){
            if (username.value.isNotEmpty()){
                Toast.makeText(context, "Please Enter Username", Toast.LENGTH_SHORT).show()
            }else if (password.value.isNotEmpty()){
                Toast.makeText(context, "Please Enter Password", Toast.LENGTH_SHORT).show()
            }else{
                    login()
            }
        }
No, that's not a issue. it seems error from "isclicked" variable.
s
Also, you seem to be doing side effects in composition with the toast triggers I would suggest giving this a read https://developer.android.com/jetpack/compose/side-effects
Your composable may recompose more times than you think, relying just on an if statement on the
isClicked
doesn’t mean that will only run once
But for your error in particular, you are doing
Copy code
var isClicked = remember {
  mutableStateOf(false)
}
But you should do
Copy code
var isClicked by remember {
  mutableStateOf(false)
}
if you want to be able to access it through
isClicked = true
instead of having to do
isClicked.value = true
p
yeah, this is the problem. thanks mate😊
are you currently doing freelance for a KMM?
s
Nope
p
do you know anyone?
s
No, and this is not the right channel for such discussions, if you are looking for something like that ask it at #hiring
588 Views