You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native中TextInput设autofocus时BottomSheet异常自动弹出问题

问题:react-native-bottom-sheet 因输入框 autofocus 导致异常自动弹出

我使用react-native-bottom-sheet实现分类选择功能,给金额输入框(Amount)设置autofocus属性后,BottomSheet会偶发自动弹出(首次打开页面时概率约2/5)。弹出时它显示在键盘后方,未遵循预设的屏幕中间停靠点,而是停在键盘上方一点。BottomSheet本应仅在点击分类输入框时才打开,进入页面时需保持隐藏。我尝试通过控制渲染变量避免初始渲染,但仍会出现短暂闪烁现象。

Bug截图

BottomSheet组件代码

const TransactionBottomSheet: React.ForwardRefRenderFunction<refProps, Props> = (props, ref) => {
  const { onSelect } = props;
  const sheetRef = useRef<BottomSheet>(null);
  const [data, setData] = useState<Transaction[]>(categoriesData);
  const [selectedCategory, setSelectedCategory] = useState<Category | null>(null);

  const openSheet = useCallback(() => {
    sheetRef.current?.expand();
  }, []);
  const closeSheet = useCallback(() => {
    sheetRef.current?.close();
  }, []);

  useImperativeHandle(ref, () => ({
    openSheet: () => openSheet(),
  }));

  const setTypeData = (id: number) => {
    const types = transactionCategories[id].types ?? [];
    setData(Object.values(types));
  };

  const clearCategory = () => {
    setData(categoriesData);
    setSelectedCategory(null);
  };

  const onRowPress = (item: Transaction | Category) => {
    if (!selectedCategory) {
      setTypeData(item.id);
      setSelectedCategory(item as Category);
    } else {
      onSelect(selectedCategory, item);
      closeSheet();
    }
  };

  const onClose = () => {
    setData(categoriesData);
    setSelectedCategory(null);
  };

  const renderItem = ({ item }: { item: Transaction | Category }) => (
    <TransactionRowSelect item={item} hideIcon={!!selectedCategory} onPress={onRowPress} />
  );

  const renderBackdrop = useCallback(
    (props) => <BottomSheetBackdrop {...props} disappearsOnIndex={-1} appearsOnIndex={0} />,
    []
  );

  return (
    <BottomSheet
      ref={sheetRef}
      snapPoints={snapPoints}
      enablePanDownToClose
      index={-1}
      onClose={onClose}
      backdropComponent={renderBackdrop}
      handleStyle={styles.handle}
    >
      <Label style={styles.title}>{"Pick category"}</Label>
      {!!selectedCategory && (
        <>
          <TransactionRowSelect item={selectedCategory} onPress={clearCategory} />
          <Separator />
        </>
      )}
      <BottomSheetFlatList
        data={data}
        keyExtractor={(item) => `${item.id}`}
        renderItem={renderItem}
      />
    </BottomSheet>
  );
};

const styles = StyleSheet.create({
  title: {
    textAlign: "center",
    fontSize: 16,
    fontWeight: "bold",
    paddingBottom: 10,
    backgroundColor: colors.grey3,
  },
  handle: {
    backgroundColor: colors.grey3,
    borderTopLeftRadius: 10,
    borderTopRightRadius: 10,
  },
});

export default React.forwardRef(TransactionBottomSheet);

添加交易页面代码

const TransactionForm: React.FC<Props> = ({ navigation }) => {
  const [date, setDate] = useState(new Date());
  const sheetRef = useRef<TransactionBottomSheetType>(null);
  const [category, setCategory] = useState<Category | null>(null);
  const [type, setType] = useState<Transaction | null>(null);
  const [amount, setAmount] = useState("");
  const [description, setDescription] = useState("");

  const [tryCreateNewTransaction, { isLoading }] = useCreateNewTransactionMutation();
  const onAdd = async () => {
    Keyboard.dismiss();
    try {
      if (type && category) {
        await tryCreateNewTransaction({
          amount: Number(amount),
          description,
          date: formatIsoDate(date),
          user_id: 1,
          type_id: type.id,
          category_id: category.id,
        }).unwrap();
        navigation.goBack();
      }
    } catch (error) {
      Alert.alert("An error occurred while adding transaction", "Please try again");
    }
  };

  const onSelectCategory = (category: Category, type: Transaction) => {
    setCategory(category);
    setType(type);
  };

  const setCategoryText = () => {
    if (!category && !type) {
      return "";
    }
    return `${category?.label}, ${type?.label}`;
  };

  const openSheet = () => {
    if (sheetRef?.current) {
      Keyboard.dismiss();
      sheetRef?.current?.openSheet();
    }
  };

  return (
    <View style={styles.container}>
      <DatePickerInput date={date} maximumDate={new Date()} onDateSelect={setDate} />
      {/* 这是自定义样式的TextInput,此处设置了autofocus属性 */}
      <LabelInput
        value={amount}
        placeholder='Amount'
        onChangeText={setAmount}
        keyboardType='decimal-pad'
        style={styles.marginTop}
        icon={<FontAwesome5 name='coins' size={24} color={colors.greenMint} />}
        autoFocus
      />
      {/* <InputErrorLabel text={errors.amount} isVisible={!!errors.amount} /> */}
      <TouchableOpacity onPress={openSheet}>
        <LabelInput
          value={setCategoryText()}
          icon={<MaterialIcons name='category' size={24} color={colors.greenMint} />}
          disabled
          placeholder='Category'
          style={styles.marginTop}
          inputStyle={styles.category}
        />
      </TouchableOpacity>
      <TextBox
        placeholder='Transaction comment'
        style={styles.marginTop}
        numberOfLines={6}
        maxLength={300}
        value={description}
        onChangeText={setDescription}
      />
      <CustomButton title='Submit' onPress={onAdd} style={styles.marginTop} />
      <AppActivityIndicator isLoading={isLoading} />
      <TransactionBottomSheet ref={sheetRef} onSelect={onSelectCategory} />
    </View>
  );
};

export default TransactionForm;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingHorizontal: 16,
    paddingTop: 20,
  },
  marginTop: {
    marginTop: 20,
  },
  category: {
    color: colors.black,
  },
});

内容的提问来源于stack exchange,提问作者sofronijev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 10:20:17