LaunchedEffect
Jetpack Composeで LaunchedEffect を使っていると、再Compose後も古い値を参照し続けることがあります。
例えばこんなコードです。
LaunchedEffect(Unit) {
snapshotFlow { ... }
.collect { index ->
selectedValue = items[index]
onSelected(index, items[index])
}
}
一見問題なさそうですが、LaunchedEffect(Unit) は初回Compose時に1回だけ起動されます。
そのため items や onSelected は起動時の値がキャプチャされ、その後外側の値が変わっても古い値を参照し続けてしまいます。
例えば、
1月 → items = 1..31
2月 → items = 1..28
に変わっても、Effect内では31日分のリストを持ち続ける可能性があります。
rememberUpdatedState
こんなときに使うのが rememberUpdatedState です。
val currentItems by rememberUpdatedState(items)
val currentOnSelected by rememberUpdatedState(onSelected)
LaunchedEffect(Unit) {
snapshotFlow { ... }
.collect { index ->
val localItems = currentItems
if (index in localItems.indices) {
selectedValue = localItems[index]
currentOnSelected(index, localItems[index])
}
}
}
rememberUpdatedState は Effect を再起動せず、参照する値だけを常に最新に保ってくれます。
使い分け
使い分けとしては以下のイメージです。
| API | 用途 |
|---|---|
| remember | 初期値を保持したい |
| rememberUpdatedState | Effect内で最新値を参照したい |
LaunchedEffect や DisposableEffect の中でコールバックやStateを使っている場合は、「古い値を握っていないか?」を一度確認してみるといいかもしれませんね。