Longpress Multipress无法正确重新渲染外部计数器

问题描述

我希望按钮在每次正常按下时都增加一个,并在长按按钮时一直增加,直到释放为止。

我正在使用TouchableOpacity longpress属性启动setInterval,看来外部道具已正确调用。但是,外部Counter组件确实会在内部更新状态,但是我们看不到任何呈现在屏幕上的更新。仅当释放按钮并再次按下(一次)时,我们才能看到它是伪装的。

为什么会这样?这是longpress属性的问题吗?

这是小吃: 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,alignItems: "center",backgroundColor: 'lightblue' }}
      onPressIn={onPress}
      onLongPress={onLongPress}
      onPressOut={cancelLongPress}>
      <Text>{props.text}</Text>
    </TouchableOpacity>
  );
};

解决方法

这是挂钩(功能示例)可能会帮助

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