[Compose Study] derivedStateOf

728x90
반응형
val result = remember(state1, state2) { calculation(state1, state2) }
val result1 = remember { derivedStateOf { calculation(state1, state2) } }

derivedStateOf

* 특정 상태가 계산되거나 다른 상태 개체에서 파생되는 경우 derivedStateOf를 사용한다.

  derivedStateOf를 사용하면 계산에 사용된 상태 중 하나가 변경될 때마다 계산이 실행된다.

 

 

* TextField에 영어알파벳을 입력하면 true로 바뀌며, Submit버튼이 활성화 되는 코드이다.

 

 

* 처음에 u를 입력했을때 버튼이 활성화 된 이후로도 나머지 usernamed을 치는동안 불필요하게 버튼에 state를 보내고 있다.

 

var username by remember { mutableStateOf("") }
val submitEnabled = remember {
	derivedStateOf { 
    	isUsernameValid(username)
    }

 

* derivedStateOf를 사용하면 위처럼 u에서 한번 상태가 활성화된 뒤, 더 이상 state를 보내지 않는다.

 

사용하는 예시

1. 스크롤이 경계값을 통과하는지 (scrollPosition > 0)
2. 리스트의 항목이 임계값보다 큰지 (아이템 > 0)
3. 위의 케이스와 같은 유효성 검사 (username.isValid())

 

FAQs

1. derivedStateOf는 remember를 사용해야 하는가?

  • composable 함수 안에서는 사용해야 함
  • derivedStateOf는 mutableStateOf 와 같이, recomposition이 일어나도 살아남아야 함
  • remember하지 않으면, recomposition할 때마다 매번 재할당됨

 

2. remember(key) 와 derivedStateOf 차이

val result = remember(state1, state2) { calculation(state1, state2) }
val result1 = remember { derivedStateOf { calculation(state1, state2) } }
  • recomposition의 횟수 차이
  • remember(key)는 key가 변경되는 만큼 업데이트가 되어야 하는 경우
    • key마다 다른 값 remember

 ex) 사용자가 LazyColumn을 스크롤한 경우에만 버튼을 활성화하는 경우

val isEnabled = lazyListState.firstVisibileItemIndex > 0

* firstVisibleItemIndex는 사용자가 스크롤하여 변경될 때마다 독자가 recompose를 유도함에 따라 0, 1, 2 등이 변경된다.
  우리는 firstVisibleItemIndex가 0보다 큰지 여부에만 관심이 있다.
  우리가 필요로 하는 입력과 출력의 양에 차이가 있으므로 여기에서 derivedStateOf를 사용하여 불필요한 recomposition을

  buffer out한다.

val isEnabled = remember {
	derivedStateOf { lazyListState.firstVisibleItemIndex > 0 }
}

 

 ex2) 매개 변수로 무언가를 계산하는 함수가 있다고 가정해보자. 
  우리는 해당 기능의 출력이 변경될 때마다 UI를 재구성하기를 원한다 (중요한 것은 해당 기능도 idempotent하다는 것이다). 
  여기서는 키 변경만큼이나 UI를 업데이트해야 하므로 키를 사용하여 기억한다. 
  즉, 입력과 출력의 양이 동일한 경우이다.

val output = remember(input) { expensiveCalculation(input) }

 

3. remember(key)와 derivedStateOf를 함께 사용하는 경우

 

@Composable
fun ScrollToTopButton(lazyListState: LazyListState, threshold: Int) {
	// 버그 있음
  	val isEnabled by remember {
    	derivedStateOf { lazyListState.firstVisibleItemIndex > threshold }
  	}
  
  	Button(onClick = { }, enabled = isEnabled) {
    	Text("Scroll to top")
  	}
}

* 초기에 threshold = 0인 경우는 잘 동작함. 

 

* 하지만 threshold가 변경되면, 조건(scrollPosition > threshold)이 맞지 않더라도 이전 값이 설정됨

 

* 이 때, threshold를 remember하게 되면, 변경될 때마다 state가 초기화 된다.

val isEnabled by remember(threshold) {
	derivedStateOf { lazyListState.firstVisibleItemIndex > threshold }
}

 

 

 

-------------------

* 출처: https://medium.com/androiddevelopers/jetpack-compose-when-should-i-use-derivedstateof-63ce7954c11b

 

Jetpack Compose — When should I use derivedStateOf?

derivedStateOf — a really common question we see is where and when is the correct place to use this API?

medium.com

https://velog.io/@beokbeok/언제-derivedStateOf를-써야할까

 

언제 derivedStateOf를 써야할까?

본 내용은 학습을 위해 Jetpack Compose — When should I use derivedStateOf? 을 보고 입맛대로 정리한 글입니다.

velog.io

 

728x90
반응형
TAGS.

Comments