Home > Software design >  Why I can't invoke lambda in the Jetpack Compose
Why I can't invoke lambda in the Jetpack Compose

Time:11-28

I want to invoke a Int value when I click on the each tab but I have an error. I used LaunchEffect() and Coroutine scope but it's not solved. how can I fix it?

Screen code:

@ExperimentalPagerApi
@Composable
fun Tabs(
    pagerState: PagerState,
    modifier: Modifier,
    state: MyJobsState,
    onTabSelected: @Composable (tabPage: Int) -> Unit
) {
    val scope = rememberCoroutineScope()
    ScrollableTabRow(
        selectedTabIndex = pagerState.currentPage,
        indicator = { tabPositions ->
            TabRowDefaults.Indicator(
                modifier.pagerTabIndicatorOffset(pagerState, tabPositions),
                height = 0.dp,
            )
        },
        edgePadding = 0.dp,
        divider = {}
    ) {
        state.items?.forEachIndexed { index, _ ->
            Tab(
                text = {
                    Text(
                        text = state.items[index].title ?: "")
                },
                selected = pagerState.currentPage == index,
                onClick = {
                    scope.launch {
                        pagerState.animateScrollToPage(index)
                    }
                    onTabSelected.invoke(index)
                }
            )
        }
    }
}

I get this error:

enter image description here

CodePudding user response:

onTabSelected is marked as @Composable, that's why you can't invoke it inside onClick.

You can only invoke @Composable inside an other @Composable, not in side effects. Remove this annotation, and you probably need to redesign the view which is using Tabs.

You're doing the same mistake again: onTabSelected is a side effect. You can't add composable views to the view hierarchy inside side effects.

Instead, you should use a state variable, and change the view depending on this state, e.g.:

var selectedTab by remember { mutableStateOf(0) }

ScrollableTabRow(
    selectedTabIndex = pagerState.currentPage,
    indicator = { tabPositions ->
        TabRowDefaults.Indicator(
            modifier.pagerTabIndicatorOffset(pagerState, tabPositions),
            height = 0.dp,
        )
    },
    edgePadding = 0.dp,
    divider = {}
) {
    state.items?.forEachIndexed { index, _ ->
        Tab(
            text = {
                Text(
                    text = state.items[index].title ?: "")
            },
            selected = pagerState.currentPage == index,
            onClick = {
                selectedTab = index
            }
        )
    }
}

when (selectedTab) {
    0 -> {
        FirstView()
    }
    1 -> {
        SecondView()
    }
}

You can find more info about state in Compose in documentation, including this youtube video which explains the basic principles.

CodePudding user response:

Remove the @Composable from your onTabSelected parameter. You can't call composables directly from a click event or any other non-composable function.

  • Related