React Native数组过滤超500项时应用崩溃问题排查
问题分析与解决方案
1. 修复option.name.toLowerCase() is not a function报错
这个错误的核心是数组里存在部分option对象的name属性不是字符串类型(可能是undefined、null或数字等)。当数组元素超过500时,遍历到这类异常元素就会触发报错。
修改过滤逻辑,添加类型校验:
const filteredOptions = options.filter((option) => { // 先确保name是字符串再执行过滤逻辑 if (typeof option.name !== 'string') return false; return option.name.toLowerCase().includes(searchValue.toLowerCase()); });
如果需要保留name为非字符串但有实际值的元素,可以先做类型转换:
const filteredOptions = options.filter((option) => { const nameStr = String(option.name || ''); // 把name转为字符串,空值转为空串 return nameStr.toLowerCase().includes(searchValue.toLowerCase()); });
2. 解决maximum call stack size exceeded栈溢出问题
直接用ScrollView+map渲染1500个元素会一次性创建所有组件,导致JS调用栈溢出,还会严重拖慢性能。换成React Native自带的**FlatList**渲染,它只会渲染当前可见区域的元素,大幅降低内存占用和渲染压力:
<FlatList data={filteredOptions} keyExtractor={(item) => item.id?.toString() || Math.random().toString()} // 优先用元素唯一ID,避免用index renderItem={({ item }) => ( <View style={{ backgroundColor: "#ddd", paddingVertical: 15, marginTop: 10, paddingHorizontal: 10, borderRadius: 8, }} > <TouchableOpacity onPress={() => handleSelection(item)}> <Text>{item.name}</Text> </TouchableOpacity> </View> )} />
3. 额外性能优化
- 防抖搜索:避免用户输入时每次字符变化都触发过滤,减少不必要的重渲染:
// 自己实现防抖函数 const debounce = (func, delay) => { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => func.apply(this, args), delay); }; }; const debouncedSetSearchValue = useCallback(debounce((text) => setSearchValue(text), 300), []); // 修改TextInput的onChangeText <TextInput // ...原有样式和属性 onChangeText={debouncedSetSearchValue} />
- 预处理数组:提前过滤掉无效元素,避免每次过滤都重复校验:
const [validOptions, setValidOptions] = useState([]); useEffect(() => { // 提前筛选出name为字符串的元素 const valid = options.filter(opt => typeof opt.name === 'string'); setValidOptions(valid); }, [options]); // 后续过滤直接用预处理后的数组 const filteredOptions = validOptions.filter((option) => { return option.name.toLowerCase().includes(searchValue.toLowerCase()); });
内容的提问来源于stack exchange,提问作者Janjac
相关产品推荐
相关产品推荐

