remember의 사용과 한계점
Composable에서 remember은 Recomposition이 일어날 때 상태를 관리하기 위해 사용된다.remember의 상태는 remember의 value를 직접 수정해주는 것으로만 가능하다.
*by 키워드는 value에 직접 접근하도록 도와주는 delegation이다. 헷갈리지 말자.
@Composable
private fun TextFieldExample() {
val text = remember { mutableStateOf("Kotlin World") }
Column(modifier = Modifier.padding(16.dp)) {
OutlinedTextField(
value = text.value,
onValueChange = { text.value = it }
)
}
}
직접 수정해주는 것만 가능하다는 것은 remember 내부의 mutableStateOf를 다시 생성하더라도 remember로 저장되는 값(val)은 업데이트가 되지 않음을 뜻한다.
*많은 사람들이 Composable의 상위 Composable에서 remember에 값을 주입해줘서 값이 업데이트 되지 않는 현상을 접한다.
예를 들어 아래의 코드를 살펴보자. 상위 Comopsable에서 text를 remember한 후 하위 Composable인 TextData에 넣어주고 있다.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
var text by remember { mutableStateOf("zzz") }
Column(modifier = Modifier.padding(16.dp)) {
OutlinedTextField(
value = text,
onValueChange = { text = it }
)
TextData(input = text)
}
}
}
}
@Composable
private fun TextData(input: String) {
val rememberedInput by remember { mutableStateOf(input) }
Text(" rememberedInput: $rememberedInput")
}
하지만 이 코드를 실행해보면 데이터가 바뀌지 않는 것을 확인할 수 있다.
왜냐하면 이미 TextData Composable에서는 "zzz"로 remember된 rememberedInput이 있고 다시 초기화가 일어나지 않기 때문이다. rememberedInput을 수정하기 위해서는 rememberedInput의 value값을 직접 수정해줘야 한다.
이를 해결하기 위한 방법은 상위에서 데이터를 받았을 때 다음과 같이 value값을 직접 수정해주는 것이다.
@Composable
private fun TextData(input: String) {
val rememberedInput by remember { mutableStateOf(input) }.apply{
value = input
}
Text(" rememberedInput: $rememberedInput")
}
위와 같이 작업하면 TextData로 들어오는 input이 바뀌었을 때 rememberedInput의 value 값이 바뀌게 되어 TextData의 Recomposition이 일어난다.
rememberUpdatedState
위의 그림2와 같은 작업이 가능해주도록 하는 것이 바로 rememberUpdatedState이다. rememberUpdatedState는 값이 들어올 때마다 새로운 value값을 remember된 mutableState에 직접 apply 해준다.
@Composable
fun <T> rememberUpdatedState(newValue: T): State<T> = remember {
mutableStateOf(newValue)
}.apply { value = newValue }
따라서 상위의 Composable의 데이터가 바뀔 때 하위 Composable의 remember된 데이터도 바뀌어야 한다면 rememberUpdatedState를 사용해야 한다.
remember과 rememberUpdatedState차이 예시
이 둘의 차이는 다음의 코드를 통해 확인할 수 있다.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
var text by remember { mutableStateOf("zzz") }
Column(modifier = Modifier.padding(16.dp)) {
OutlinedTextField(
value = text,
onValueChange = { text = it }
)
TextData(input = text)
}
}
}
}
@Composable
private fun TextData(input: String) {
val rememberedInput by remember { mutableStateOf(input) }
val rememberedUpdatedInput by rememberUpdatedState(input)
Text(" rememberedInput: $rememberedInput")
Text(" rememberedUpdatedStateInput: ${rememberedUpdatedInput}")
}
위 코드를 수행하면 다음의 결과가 나온다.