Jetpack Compose: How to pass values to composables in the tree?

I'am using Compose now with passing parameters to functions, but I feel, those parameters are getting longer with each new data to be passed down the tree.

I am wondering if there is a way to pass values to other composables down the tree.

Upvotes: 6

Views: 9479

Answers (1)

Other than using function arguments for Composables (the recommended way), you can use CompositionLocal: Avoid CompositionLocal for concepts that aren't thought as tree-scoped or sub-hierarchy scoped.

First, define variable of compositionLocalOf globally (e.g., in LocalCompositions.kt):

import androidx.compose.runtime.compositionLocalOf

data class Post(val title: String)
val LocalPost = compositionLocalOf { Post(title = "Ahmed") }

and then define it inside @Compose function to be used by other composables down the tree:

@Composable
fun MainView() {
  ...
  val post = Post(title = "Shamil")

  CompositionLocalProvider(LocalPost provides post) {
    PostContentView()
  }
  ...
}

Now, retrieve the value inside a @Composable:

// composable down the nodes tree
@Composable
fun PostContentView() {
  ...
  val post = LocalPost.current
  ...
}

Observe variable changes

If you want to achieve the above solution but with watching changes to the variable and update the composable (node) accordingly, you can use MutableState variable.

Redefining the previous example:

LocalCompositions.kt:

import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.mutableStateOf

data class Post(val title: MutableState<String> = mutableStateOf(""))
val LocalPost = compositionLocalOf { Post(title = mutableStateOf("Ahmed")) }

and then define it inside @Compose function to be used by other composables down the tree:

@Composable
fun MainView() {
  ...
  val post = Post(title = remember { mutableStateOf("Shamil") })

  CompositionLocalProvider(LocalPost provides post) {
    PostContentView()
  }
  ...

  post.title.value = "Ali"

  ...
}

Now, retrieve the value inside a @Composable:

// composable down the nodes tree
@Composable
fun PostContentView() {
  ...
  val post = LocalPost.current

  // now this composable will be updated whenever post.title value is updated

  if (post.title.value == "Jamal") {
   ...
  } 

  ...
}

Upvotes: 8

Related Questions