Search code examples
androidkotlinandroid-studioandroid-jetpack-composeside-effects

How to pass a value from a composable function to another composable function and return it modified to the caller function in kotlin?


I've started recently to learn Android and develop my own personal application. More precisely, I want to make a budget tracker and the problem I've just stumbled on is, as mentioned in the title, about how can I send a parameter to a composable function and return it modified to the caller. Both the caller and the callee are composables. I already know, a composable function has the type Unit so it doesn't explicitly return anything (just like void in other languages). The only other way that comes to my mind is to make some sort of MutableState<...> variable and pass it between the 2 functions as a side effect through parameters. Is this the only solution? And if it is a solution what is the impact or change of meaning between using remember or rememberSaveable constructs and how should I implement it (a brief explanation would be welcomed)?

To give a bit more context, I am currently working on a screen where the transactions will be listed. This screen has an "add" and a "delete" button for the transactions. The "add" button triggers the call of another composable function which shows a card that plays the role of a form where the details of the transactions should be entered. One of the fields is the dropdown menu (another composable) of the currencies. Once you select a currency and return to the main form the name of currency should somehow be passed back from the dropdown composable to the form composable in the form of a String or even a wrapper class with a field of type String.

Thanks a lot in advance.


Solution

  • Compose functions must not have any side effects (except those explicity designed as such, as the SideEffect or LaunchedEffect composables).

    Instead, the idea is to pass down a callback, like this:

    @Composable
    fun Form() {
        var currency by remember { mutableStateOf("") }
    
        CurrencyDropdown(currency) {
            currency = it
        }
    }
    
    @Composable
    fun CurrencyDropdown(
        selected: String,
        onSelect: (String) -> Unit,
    ) {
           // when a new currency was selected, call:
           // onSelect("USD")
    }
    

    The paradigm is to only pass data (state) down, where events are passed up. This is called Unidirectional data flow. See https://developer.android.com/jetpack/compose/architecture#udf for more.