虽然答案在技术上是正确的,但第一个示例渲染了太多次,不幸的是我不理解第二个示例。
所以我回到了React
看看那里是如何完成的,并且解释得很好here https://usehooks.com/usePrevious/:
这就是钩子(remember
函数如你所愿)看起来像(对于好奇的人来说):
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
功能,但我发现remember
在我的情况下不起作用,因为即使没有keys
被传入。
Usage:
@Composable
fun SomeComponent() {
...
val prevValue = rememberPrevious(currentValue)
}