Longpress multipress 没有正确重新渲染外部计数器
Longpress multipress not rerendering outer counter correctly
我希望按钮在每次正常按下时将数字递增 1,并在长按按钮时继续递增,直到松开。
我正在使用 TouchableOpacity 长按 属性 来启动 setInterval,看起来外部 props 被正确调用了。但是,外部 Counter 组件确实会在内部更新状态,但我们看不到任何更新呈现到屏幕上。只有松开按钮再按一次(一次)才可以看出变相算了。
为什么会这样?这是长按 属性 的问题吗?
这是小吃:
https://snack.expo.io/xXP_PiqIy
代码如下:
import React, { useRef, useState } from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
export default function App() {
const [count, setCount] = useState(10)
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>{count}</Text>
<CounterButton onPress={(count) => setCount(count)} initialCount={10} />
</View>
);
}
const CounterButton = (props) => {
const [count, setCount] = useState(props.initialCount ?? 0);
const onPress = () => {
props.onPress(count + 1);
setCount((count) => count + 1);
};
return <MultiTouchable onPress={onPress} text={' + '} />;
};
const MultiTouchable = (props) => {
const isPressing = useRef(false);
const timer = useRef();
const onPress = () => {
props.onPress();
};
const onLongPress = () => {
isPressing.current = true;
timer.current = setInterval(onPress, 200);
};
const cancelLongPress = () => {
if (isPressing.current) {
clearInterval(timer.current);
isPressing.current = false;
}
};
return (
<TouchableOpacity
style={{ width: 50, height: 50, justifyContent: "center", alignItems: "center", backgroundColor: 'lightblue' }}
onPressIn={onPress}
onLongPress={onLongPress}
onPressOut={cancelLongPress}>
<Text>{props.text}</Text>
</TouchableOpacity>
);
};
这是 Hooks(功能示例)可能会有所帮助
import React from "react";
import {
SafeAreaView,
View,
Dimensions,
TouchableOpacity,
Text
} from "react-native";
const App (props) => {
const [counter, setCounter] = React.useState(0);
const [timer, setTimer] = React.useState(null);
const addOne = () => {
setCounter( counter + 1 );
setTimer(setTimeout(addOne, 200) );
};
const stopTimer = () => {
clearTimeout(timer);
};
render() {
return (
<SafeAreaView>
<View style={{ flex:1 }}>
<TouchableOpacity
style={{ backgroundColor: "#FFC0CB" }}
onPressIn={addOne}
onPressOut={stopTimer}
>
<Text>Press to start</Text>
</TouchableOpacity>
<Text>{counter}</Text>
</View>
</SafeAreaView>
);
}
}
看起来问题根本不是长按问题。
我需要更新计数器 并且 在 setCounter 回调 中调用 props.onPress
,就像这样
如果有人能在评论中解释为什么需要在这里完成,我会非常高兴。
// CounterButton
// ❌ doesn't work
const onPress = () => {
props.onPress(count + 1);
setCount((count) => count + 1);
};
// ✅ works
const onPress = () => {
setCount((count) => {
onPress(count + 1);
return count + 1;
});
};
我希望按钮在每次正常按下时将数字递增 1,并在长按按钮时继续递增,直到松开。
我正在使用 TouchableOpacity 长按 属性 来启动 setInterval,看起来外部 props 被正确调用了。但是,外部 Counter 组件确实会在内部更新状态,但我们看不到任何更新呈现到屏幕上。只有松开按钮再按一次(一次)才可以看出变相算了。
为什么会这样?这是长按 属性 的问题吗?
这是小吃: https://snack.expo.io/xXP_PiqIy
代码如下:
import React, { useRef, useState } from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
export default function App() {
const [count, setCount] = useState(10)
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>{count}</Text>
<CounterButton onPress={(count) => setCount(count)} initialCount={10} />
</View>
);
}
const CounterButton = (props) => {
const [count, setCount] = useState(props.initialCount ?? 0);
const onPress = () => {
props.onPress(count + 1);
setCount((count) => count + 1);
};
return <MultiTouchable onPress={onPress} text={' + '} />;
};
const MultiTouchable = (props) => {
const isPressing = useRef(false);
const timer = useRef();
const onPress = () => {
props.onPress();
};
const onLongPress = () => {
isPressing.current = true;
timer.current = setInterval(onPress, 200);
};
const cancelLongPress = () => {
if (isPressing.current) {
clearInterval(timer.current);
isPressing.current = false;
}
};
return (
<TouchableOpacity
style={{ width: 50, height: 50, justifyContent: "center", alignItems: "center", backgroundColor: 'lightblue' }}
onPressIn={onPress}
onLongPress={onLongPress}
onPressOut={cancelLongPress}>
<Text>{props.text}</Text>
</TouchableOpacity>
);
};
这是 Hooks(功能示例)可能会有所帮助
import React from "react";
import {
SafeAreaView,
View,
Dimensions,
TouchableOpacity,
Text
} from "react-native";
const App (props) => {
const [counter, setCounter] = React.useState(0);
const [timer, setTimer] = React.useState(null);
const addOne = () => {
setCounter( counter + 1 );
setTimer(setTimeout(addOne, 200) );
};
const stopTimer = () => {
clearTimeout(timer);
};
render() {
return (
<SafeAreaView>
<View style={{ flex:1 }}>
<TouchableOpacity
style={{ backgroundColor: "#FFC0CB" }}
onPressIn={addOne}
onPressOut={stopTimer}
>
<Text>Press to start</Text>
</TouchableOpacity>
<Text>{counter}</Text>
</View>
</SafeAreaView>
);
}
}
看起来问题根本不是长按问题。
我需要更新计数器 并且 在 setCounter 回调 中调用 props.onPress
,就像这样
如果有人能在评论中解释为什么需要在这里完成,我会非常高兴。
// CounterButton
// ❌ doesn't work
const onPress = () => {
props.onPress(count + 1);
setCount((count) => count + 1);
};
// ✅ works
const onPress = () => {
setCount((count) => {
onPress(count + 1);
return count + 1;
});
};