虽然答案在技术上是正确的,但第一个示例渲染次数过多,不幸的是我没有理解第二个示例。
所以我回到React 看看它是如何在那里完成的,并且解释得很好here:
这就是钩子(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,它也总是会重新渲染。
用法:
@Composable
fun SomeComponent() {
...
val prevValue = rememberPrevious(currentValue)
}