已合并
fix: the infinite loop caused by the error 'Animated node with tag xxx does not exist'. #1698
xiedairong创建于 2025年10月20日
fix: the infinite loop caused by the error 'Animated node with tag xxx does not exist'. #1698
已合并
共 2 个文件变更+62-3
| @@ -436,9 +436,13 @@ int32_t AnimatedNodesManager::getMinAcceptableFrameRate( | |||
| 436 | const std::vector<facebook::react::Tag>& valueNodeTags) { | 436 | const std::vector<facebook::react::Tag>& valueNodeTags) { |
| 437 | int32_t finalFrameRate = 30; | 437 | int32_t finalFrameRate = 30; |
| 438 | for (const auto& tag : valueNodeTags) { | 438 | for (const auto& tag : valueNodeTags) { |
| 439 | - auto& node = getValueNodeByTag(tag); | 439 | + try { |
| 440 | - int32_t currentFrameRate = node.getFrameRate(); | 440 | + auto& node = getValueNodeByTag(tag); |
| 441 | - finalFrameRate = std::max(finalFrameRate, currentFrameRate); | 441 | + int32_t currentFrameRate = node.getFrameRate(); |
| 442 | + finalFrameRate = std::max(finalFrameRate, currentFrameRate); | ||
| 443 | + } catch (std::out_of_range& _e) { | ||
| 444 | + // if a node is not found we skip over it | ||
| 445 | + } | ||
| 442 | } | 446 | } |
| 443 | return finalFrameRate; | 447 | return finalFrameRate; |
| 444 | } | 448 | } |
| @@ -93,10 +93,65 @@ export function AnimatedTest() { | |||
| 93 | <TestCase.Example itShould="move red square horizontally relatively to the scroll offset (attachNativeEvent)"> | 93 | <TestCase.Example itShould="move red square horizontally relatively to the scroll offset (attachNativeEvent)"> |
| 94 | <AnimatedAttachNativeEventTest /> | 94 | <AnimatedAttachNativeEventTest /> |
| 95 | </TestCase.Example> | 95 | </TestCase.Example> |
| 96 | + <TestCase.Example itShould="after the loading animation ends, move square immediately when pressing button"> | ||
| 97 | + <RemoveNodeAndStartNewAnimatedExample /> | ||
| 98 | + </TestCase.Example> | ||
| 96 | </TestSuite> | 99 | </TestSuite> |
| 97 | ); | 100 | ); |
| 98 | } | 101 | } |
| 99 | 102 | ||
| 103 | +const Loading = () => { | ||
| 104 | + const opacity = useRef(new Animated.Value(0.2)).current; | ||
| 105 | + const runAmimation = () => { | ||
| 106 | + Animated.sequence([ | ||
| 107 | + Animated.timing(opacity, { | ||
| 108 | + toValue: 1, | ||
| 109 | + duration: 600, | ||
| 110 | + useNativeDriver: true, | ||
| 111 | + }), | ||
| 112 | + Animated.timing(opacity, { | ||
| 113 | + toValue: 0.2, | ||
| 114 | + duration: 600, | ||
| 115 | + useNativeDriver: true, | ||
| 116 | + }), | ||
| 117 | + ]).start(() => { | ||
| 118 | + runAmimation(); | ||
| 119 | + }); | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + useEffect(() => { | ||
| 123 | + runAmimation() | ||
| 124 | + }, []) | ||
| 125 | + | ||
| 126 | + return ( | ||
| 127 | + <Animated.View | ||
| 128 | + style={[ | ||
| 129 | + { | ||
| 130 | + height: '100%', | ||
| 131 | + width: '100%', | ||
| 132 | + backgroundColor: 'pink', | ||
| 133 | + opacity, | ||
| 134 | + } | ||
| 135 | + ]} | ||
| 136 | + /> | ||
| 137 | + ) | ||
| 138 | +} | ||
| 139 | + | ||
| 140 | +const RemoveNodeAndStartNewAnimatedExample = () => { | ||
| 141 | + const [show, setShow] = useState(false) | ||
| 142 | + useEffect(() => { | ||
| 143 | + setTimeout(() => { | ||
| 144 | + setShow(true); | ||
| 145 | + }, 6000) | ||
| 146 | + }, []) | ||
| 147 | + | ||
| 148 | + return ( | ||
| 149 | + <View style={{ height: 72 }}> | ||
| 150 | + {show ? <DiffClamp /> : <Loading />} | ||
| 151 | + </View> | ||
| 152 | + ); | ||
| 153 | +} | ||
| 154 | + | ||
| 100 | const AnimatedAttachNativeEventTest = () => { | 155 | const AnimatedAttachNativeEventTest = () => { |
| 101 | const ref = useRef<ScrollView>(null); | 156 | const ref = useRef<ScrollView>(null); |
| 102 | const animatedValue = new Animated.Value(0); | 157 | const animatedValue = new Animated.Value(0); |