Image
Android Jetpack Compose/Compose State

[Compose State] remember과 rememberUpdatedState를 사용한 상태 관리

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")
}

 

하지만 이 코드를 실행해보면 데이터가 바뀌지 않는 것을 확인할 수 있다. 

 

그림1. 바뀌지 않는 remember

 

왜냐하면 이미 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이 일어난다.

 

그림2. 바뀌는 remember

 

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}")
}

 

위 코드를 수행하면 다음의 결과가 나온다.

 

그림3. remember과 rememberUpdatedState의 차이

반응형

 

이 글의 저작권은 '조세영의 Kotlin World' 에 있습니다. 글, 이미지 무단 재배포 및 변경을 금지합니다.

 

 

Kotlin, Android, Spring 사용자 오픈 카톡

오셔서 궁금한 점을 질문해보세요!
비밀번호 : kotlin22

open.kakao.com