본문 바로가기

Jetpack Compose

[Jetpack Compose Side-effects] 3. rememberUpdatedState

rememberUpdatedState

remember는 recomposition이 일어날 때 상태를 관리하기 위해서 사용합니다. remember의 상태를 변경하는 유일한 방법은 value 키워드를 이용해 직접 수정해주는 것 입니다. 따라서 상위 Composable에서 값이 변경되어도 하위 Composable에서 remember로 변수가 만들어졌다면 바뀐 State를 내려주어도, value 키워드로 수정해준 것이 아니기 때문에 하위 Composable에서 변수의 value가 바뀌지 않습니다.

 

아래의 코드를 살펴보면 하위 Composable인 ResultText에서 input을 인자로 받아 rememberResult 변수를 remeber를 활용해 초기화하고 있습니다. 이렇게 remember를 활용한 경우, SideEffectScreen의 value 값이 변해서 IncreaseValue로 전달하는 값이 변해도 rememberResult의 value는 초기의 input 값을 유지해 아무런 변화가 나타나지 않습니다. 

 

반면 rememberUpdatedState를 이용하면 input의 값이 변하면 내부적으로 remember의 value에 접근해 값을 업데이트해주면서 넘겨받은 input 값으로 rememberUpdatedStateValue의 값이 변하게 됩니다.

 

@Composable
fun SideEffectScreen() {
    Surface(
        modifier = Modifier.fillMaxSize()
    ) {
        var value by remember { mutableIntStateOf(0) }

        Column(
            modifier = Modifier.fillMaxSize(),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center
        ) {
            ResultText(result = value)

            Spacer(modifier = Modifier.height(12.dp))

            Button(
                modifier = Modifier.wrapContentSize(),
                onClick = {
                    value ++
                }
            ) {
                Text("Click!")
            }
        }
    }
}

@Composable
private fun ResultText(result: Int) {
    val rememberUpdatedStateResult by rememberUpdatedState(result)
    val rememberResult by remember { mutableIntStateOf(result) }

    Text(
        modifier = Modifier.fillMaxWidth(),
        text = "rememberUpdatedStateValue : ${rememberUpdatedStateResult}, rememberedValue : ${rememberResult}",
        textAlign = TextAlign.Center
    )
}

 

rememberUpdatedState와 remember의 차이

 

rememberUpdatedState의 값이 변할 수 있는 이유는 내부 구현을 보면 쉽게 알 수 있습니다. 바로 apply를 통해 value에 새로운 값을 넣어주기 때문입니다.

 

@Composable
fun <T> rememberUpdatedState(newValue: T): State<T> = remember {
    mutableStateOf(newValue)
}.apply { value = newValue }