React native 运行 useState/force 在 worklet 函数中重新渲染
React native run useState/force rerender inside worklet funtion
我正在从 react-native-reanimated 调用 useAnimatedScrollHandler
挂钩来处理我在 Animated.ScrollView
上的 onScroll
函数。此挂钩按预期工作,但我现在想禁用基于 currentIndex
的自定义按钮 (My FlatButton),它是 sharedValue
。但是当 sharedValue 改变时,屏幕不会被重新渲染,因为状态没有改变,所以我的按钮的外观保持不变。
有没有办法在工作集内强制重新渲染,或者是否可以使用 useState
从工作集内强制重新渲染?
const scrollHandler = useAnimatedScrollHandler((event) => {
translationX.value = event.contentOffset.x
if (event.contentOffset.x < width * 0.5 && currentIndex.value != 0) {
currentIndex.value = 0
} else if (
event.contentOffset.x > width * 0.5 &&
event.contentOffset.x < width * 1.5 &&
currentIndex.value != 1
) {
currentIndex.value = 1
} else if (event.contentOffset.x > width * 1.5 && currentIndex.value != 2) {
currentIndex.value = 2
}
})
<FlatButton
label="Next"
disabled={
(currentIndex.value == 0 && (!firstName || !lastName)) ||
(currentIndex.value == 1 && (!dateOfBirth || !sex)) ||
(currentIndex.value == 2 &&
(!streetNumber || !postalCode || !city || !state || !country))
}
onPress={() => {
if (currentIndex.value == 0) {
scrollRef.current
?.getNode()
.scrollTo({ x: width, animated: true })
} else if (currentIndex.value == 1) {
scrollRef.current?.getNode().scrollToEnd({ animated: true })
}
}}
/>
我刚刚发现 reanimated 提供了 runOnJS 函数,这使得 运行 像 setState
这样的 javscript 函数在 worklet 中成为可能。因此,只需创建一个包装函数,就像我的情况 toggleIndex
一样,您可以在其中与您的状态进行交互,并从您的工作集中在 runOnJS
中调用此函数。
const [currentIndex, setCurrentIndex] = useState(0)
const toggleIndex = (index: number) => {
setCurrentIndex(index)
}
const scrollHandler = useAnimatedScrollHandler((event) => {
translationX.value = event.contentOffset.x
if (event.contentOffset.x < width * 0.5 && currentIndex != 0) {
runOnJS(toggleIndex)(0)
} else if (
event.contentOffset.x > width * 0.5 &&
event.contentOffset.x < width * 1.5 &&
currentIndex != 1
) {
runOnJS(toggleIndex)(1)
} else if (event.contentOffset.x > width * 1.5 && currentIndex != 2) {
runOnJS(toggleIndex)(2)
}
})
我正在从 react-native-reanimated 调用 useAnimatedScrollHandler
挂钩来处理我在 Animated.ScrollView
上的 onScroll
函数。此挂钩按预期工作,但我现在想禁用基于 currentIndex
的自定义按钮 (My FlatButton),它是 sharedValue
。但是当 sharedValue 改变时,屏幕不会被重新渲染,因为状态没有改变,所以我的按钮的外观保持不变。
有没有办法在工作集内强制重新渲染,或者是否可以使用 useState
从工作集内强制重新渲染?
const scrollHandler = useAnimatedScrollHandler((event) => {
translationX.value = event.contentOffset.x
if (event.contentOffset.x < width * 0.5 && currentIndex.value != 0) {
currentIndex.value = 0
} else if (
event.contentOffset.x > width * 0.5 &&
event.contentOffset.x < width * 1.5 &&
currentIndex.value != 1
) {
currentIndex.value = 1
} else if (event.contentOffset.x > width * 1.5 && currentIndex.value != 2) {
currentIndex.value = 2
}
})
<FlatButton
label="Next"
disabled={
(currentIndex.value == 0 && (!firstName || !lastName)) ||
(currentIndex.value == 1 && (!dateOfBirth || !sex)) ||
(currentIndex.value == 2 &&
(!streetNumber || !postalCode || !city || !state || !country))
}
onPress={() => {
if (currentIndex.value == 0) {
scrollRef.current
?.getNode()
.scrollTo({ x: width, animated: true })
} else if (currentIndex.value == 1) {
scrollRef.current?.getNode().scrollToEnd({ animated: true })
}
}}
/>
我刚刚发现 reanimated 提供了 runOnJS 函数,这使得 运行 像 setState
这样的 javscript 函数在 worklet 中成为可能。因此,只需创建一个包装函数,就像我的情况 toggleIndex
一样,您可以在其中与您的状态进行交互,并从您的工作集中在 runOnJS
中调用此函数。
const [currentIndex, setCurrentIndex] = useState(0)
const toggleIndex = (index: number) => {
setCurrentIndex(index)
}
const scrollHandler = useAnimatedScrollHandler((event) => {
translationX.value = event.contentOffset.x
if (event.contentOffset.x < width * 0.5 && currentIndex != 0) {
runOnJS(toggleIndex)(0)
} else if (
event.contentOffset.x > width * 0.5 &&
event.contentOffset.x < width * 1.5 &&
currentIndex != 1
) {
runOnJS(toggleIndex)(1)
} else if (event.contentOffset.x > width * 1.5 && currentIndex != 2) {
runOnJS(toggleIndex)(2)
}
})