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

react-native-smooth-picker@1.1.3滚动时scrollToIndex报错及选中值异常问题排查与修复建议

解决 react-native-smooth-picker@1.1.3 的两个核心问题

我来帮你分析这两个问题的根源,并且给出具体的修复方案:

问题1:scrollToIndex is not a function 错误

这个错误有两个主要原因:

  • 你没有在代码中声明 refPicker 变量(直接用了 ref={refPicker},但没定义 const refPicker = React.useRef(null);),不过即使声明了,react-native-smooth-picker 的组件ref并不暴露 scrollToIndex 方法——这个方法是React Native原生ScrollView的API,而该库没有把内部ScrollView的ref透传出来。
  • 更关键的是:你完全不需要手动调用 scrollToIndex!因为你已经开启了 magnet 属性,这个属性会让组件自动将选中的项吸附到中间位置,手动调用反而会和库的内置逻辑冲突。

问题2:滚动时无法正确选中值并更新状态

这个问题的核心问题出在数据处理和状态更新逻辑的混乱:

  1. data 属性的map函数没有返回值:dataRows.map((o)=> { // let obj; return o.name }) 这行代码里,你把return注释掉了,导致每个item都是undefined,所以onSelected里的item是undefined,自然找不到对应的数据,setValue也就无法正确更新。
  2. 重复的状态更新逻辑:你在onSelected里调用handleChange,而handleChange又去设置selected状态,同时还尝试手动滚动,这会导致状态更新的竞态,让组件的选中状态和你的本地selected状态不同步。
  3. ItemToRender组件没有返回任何JSX元素:你的代码里return ;是空的,这会导致选择器无法渲染任何选项,也是潜在的问题。

完整修复代码

下面是修复后的完整代码,我已经标注了关键的修改点:

import React from "react";
import { Text, View } from "react-native";
import SmoothPicker from "react-native-smooth-picker";

const opacities = { 0: 1, 1: 1, 2: 0.6, 3: 0.3, 4: 0.1 };
const sizeText = { 0: 20, 1: 15, 2: 10 };

// 修复:让组件返回正确的JSX元素
const ItemToRender = ({ item, index }, indexSelected, vertical) => {
  const selected = index === indexSelected;
  const gap = Math.abs(index - indexSelected);
  const opacity = gap > 3 ? opacities[4] : opacities[gap];
  const fontSize = gap > 1 ? sizeText[2] : sizeText[gap];

  return (
    <View style={{ justifyContent: "center", alignItems: "center" }}>
      <Text style={{ opacity, fontSize, color: selected ? "#000" : "#999" }}>
        {item}
      </Text>
    </View>
  );
};

export default function SmoothPickerScreen({ navigation }) {
  const [selectedIndex, setSelectedIndex] = React.useState(1);
  const [value, setValue] = React.useState(null);
  const [dataRows, setDataRows] = React.useState([]);

  const data = [
    { name: "A1", id: 1 },
    { name: "A2", id: 2 },
    { name: "A3", id: 3 },
    { name: "A4", id: 4 },
    { name: "A5", id: 5 },
    { name: "A6", id: 6 },
    { name: "A7", id: 7 },
    { name: "A8", id: 8 },
    { name: "A9", id: 9 },
    { name: "A10", id: 10 },
  ];

  React.useEffect(() => {
    setDataRows(data);
    // 初始化时设置默认值
    setValue(data[selectedIndex].id);
  }, []);

  // 合并状态更新逻辑,移除多余的handleChange
  const handleSelect = ({ item, index }) => {
    setSelectedIndex(index);
    const foundItem = dataRows.find((o) => o.name === item);
    if (foundItem) {
      setValue(foundItem.id);
    }
  };

  return (
    <View style={{ flex: 1, justifyContent: "center" }}>
      <SmoothPicker
        // 移除无用的ref,因为库不支持scrollToIndex
        keyExtractor={(_, index) => index.toString()}
        showsVerticalScrollIndicator={false}
        // 修复:正确返回item的name值
        data={dataRows.map((o) => o.name)}
        scrollAnimation
        // 修复:直接使用合并后的handleSelect处理选中事件
        onSelected={handleSelect}
        renderItem={(option) => ItemToRender(option, selectedIndex, true)}
        magnet
      />
      {/* 可以添加一个文本显示当前选中的值,方便调试 */}
      <Text style={{ marginTop: 20, textAlign: "center" }}>
        当前选中ID:{value}
      </Text>
    </View>
  );
}

关键修改说明

  1. 移除了refPicker和手动滚动逻辑:依赖magnet属性自动完成选中项的定位。
  2. 修复了data的map处理:确保每个item都是有效的名称字符串。
  3. 合并了状态更新逻辑:在handleSelect中同时更新选中索引和对应的值,避免状态不同步。
  4. 修复了ItemToRender的返回值:添加了Text组件来渲染选项内容,并应用了样式。
  5. 初始化时设置默认值:在useEffect中初始化value为默认选中项的ID,让页面加载时就有正确的初始状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 03:29:08