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;
  });
};