![](/img/trans.png)
[英]onClick called repeatedly (not supposed to) when component re-renders
[英]Component re-renders when setState called
反應原生 PanResponder 可拖動被 setState 中斷
我有一個 state 變量來跟蹤秒數
const [seconds, setSeconds] = useState(0)
useEffect(() => {
const interval = setInterval(() => {
if (seconds > 59) {
setSeconds(0)
} else {
setSeconds((seconds) => seconds + 1)
}
}, 1000)
return () => clearInterval(interval)
}, [seconds])
我也在使用可拖動的平移響應器
import React, { useState, useRef, ReactNode } from 'react'
import {
StyleSheet,
Animated,
PanResponder,
PanResponderGestureState,
Text
} from 'react-native'
const Draggable = (props) => {
const { draggable, isDropZone, moveToDropArea } = props
const [showDraggable, setshowDraggable] = useState(true)
const pan = useRef<Animated.AnimatedValueXY>(new Animated.ValueXY()).current
const panResponder = PanResponder.create({
onStartShouldSetPanResponder: () => true,
onPanResponderMove: Animated.event([
null,
{
dx: pan.x,
dy: pan.y,
},
]),
onPanResponderRelease: (e, gesture) => {
if (isDropZone(gesture)) {
setshowDraggable(false)
moveToDropArea()
} else {
Animated.spring(pan, {
toValue: { x: 0, y: 0 },
useNativeDriver: false,
}).start()
}
pan.flattenOffset()
},
})
return (
<Animated.View {...panResponder.panHandlers} style={[pan.getLayout()]}>
<Text>{seconds}</Text>
</Animated.View>
)
}
當我嘗試拖動可拖動對象時,它會移動,但是當 state 更新組件時,組件會重新渲染,並且 Draggable 項目會回到原來的位置。
如何防止這種情況?
提前致謝。
嘗試像這樣編寫你的 useEffect 鈎子:
useEffect(() => {
const interval = setInterval(() => {
setSeconds(currentSeconds => currentSeconds > 59 ? 0 : currentSeconds + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
這樣它就不會在每秒鍾的 state 變化時觸發。
但是,更改 state 仍會使您的組件重新渲染。 如果你想防止重新渲染,你應該使用 useRef 而不是 useState。
const seconds = useRef(0);
useEffect(() => {
const interval = setInterval(() => {
seconds.current = seconds.current > 59 ? 0 : seconds.current + 1;
}, 1000);
return () => clearInterval(interval);
}, [seconds]);
console.log(seconds.current); // will log the last saved number of seconds before the last re-render
但是如果你需要顯示秒的變化,你需要你的組件在秒 state 變化時重新渲染。 在這種情況下,我建議您將滾動邏輯分離到另一個(可能是父)組件,這樣它就不會在由秒的 state 更改引起的重新渲染時被重置。
在 useEffect 鈎子的第二個參數中傳遞空數組。
useEffect hook 在組件掛載到 dom 時運行回調 function,類似於 class 組件中的 componentDidMount 生命周期方法。
setInterval function 每隔一秒運行一次 setSeconds 方法。
在 useEffect 鈎子中,我們返回一個帶有計時器參數的 clearInterval function,因此當組件從 dom 卸載時,setInterval function 會停止,這類似於 componentWillUnmount 方法。
空數組將在掛載時運行 useEffect,在其整個生命周期中保持沉默。
useEffect(() => {
const interval = setInterval(() => {
if (seconds > 59) {
setSeconds(0)
} else {
setSeconds((seconds) => seconds + 1)
}
}, 1000)
return () => clearInterval(interval)
},[])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.