[英]Get previous value of state in Composable - Jetpack Compose
假设我的代码看起来像这样
@Composable
fun ExampleList() {
val tickers by exampleViewModel.tickers.observeAsState()
LazyColumn() {
items(items = tickers) { ticker ->
ExampleItem(ticker)
}
}
}
@Composable
fun ExampleItem(ticker: Ticker) {
Text(text= ticker.lastPrice)
}
每次更新代码时,是否有在 ExampleItem Compose 中获取代码的先前值?
我想知道 React Native 中是否有类似 componentDidUpdate 的东西
我发现我可以通过使用remember {mutableStateOf}
来获得ticker的最后一个值,如下所示:
var lastTicker by remember { mutableStateOf(ticker)}
SideEffect {
if (lastTicker != ticker) {
// compare lastTicker to current ticker before assign new value
lastTicker = ticker
}
}
通过使用remember { mutableStateOf(ticker)}
,我可以通过重组来保持股票的价值。
然后在 SideEffect 中,我可以使用 lastTicker 值(在我的情况下比较最后一个代码和当前代码),然后将它分配给新值以用于下一个组合
或使用derivedStateOf
只观察股票的变化,避免重组
val compareValue by remember(ticker) {
derivedStateOf {
// compare lastTicker to current ticker before assign new value
lastTicker = ticker
// return value
}
}
虽然答案在技术上是正确的,但第一个示例渲染次数过多,不幸的是我不理解第二个示例。
所以我回到React
看看它是如何在那里完成的,这里解释得很好:
这就是钩子( remember
function )的样子(对于好奇的人):
function usePrevious<T>(value: T): T {
// The ref object is a generic container whose current property is mutable ...
// ... and can hold any value, similar to an instance property on a class
const ref: any = useRef<T>();
// Store current value in ref
useEffect(() => {
ref.current = value;
}, [value]); // Only re-run if value changes
// Return previous value (happens before update in useEffect above)
return ref.current;
}
相同的想法可以在 compose 中以可重用的方式实现(重要的是,在设置先前的值时不应重新渲染@Composable
):
/**
* Returns a dummy MutableState that does not cause render when setting it
*/
@Composable
fun <T> rememberRef(): MutableState<T?> {
// for some reason it always recreated the value with vararg keys,
// leaving out the keys as a parameter for remember for now
return remember() {
object: MutableState<T?> {
override var value: T? = null
override fun component1(): T? = value
override fun component2(): (T?) -> Unit = { value = it }
}
}
}
和实际的rememberPrevious
:
@Composable
fun <T> rememberPrevious(
current: T,
shouldUpdate: (prev: T?, curr: T) -> Boolean = { a: T?, b: T -> a != b },
): T? {
val ref = rememberRef<T>()
// launched after render, so the current render will have the old value anyway
SideEffect {
if (shouldUpdate(ref.value, current)) {
ref.value = current
}
}
return ref.value
}
可以将key
添加到remember
function,但我发现remember
在我的情况下不起作用,因为即使没有传入任何keys
,它也总是重新渲染。
用法:
@Composable
fun SomeComponent() {
...
val prevValue = rememberPrevious(currentValue)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.