React Native中FlatList展示搜索结果时非可迭代实例展开错误求助
解决FlatList搜索功能中的“非可迭代实例展开”错误
错误原因拆解
- 错误的数组展开操作:
setResult方法里尝试展开整个API返回对象res(这是包含data、error的对象,并非数组)到数组中,触发“非可迭代实例”报错。同时getData中已对data赋值,又重复调用setResult,造成数据逻辑混乱。 - 直接修改React状态:
updateSearch里直接给this.state.data赋值,违反React状态不可直接修改的规则,导致状态更新不生效,搜索结果无法正常展示。 - 无效的keyExtractor:
FlatList的keyExtractor使用了link字段,但API返回的条目里不存在该字段,会引发渲染异常。
修复步骤
- 删除冗余的
setResult方法,在getData中直接初始化data和temp状态,确保两者都存储API返回的合法公司数组。 - 修改
updateSearch,通过setState更新过滤后的data,不再直接操作this.state。 - 修正
keyExtractor,使用每个条目自带的id作为唯一键值。
完整修正代码
import { Box, Text, Image, Heading, Center, ScrollView, Spinner, FlatList, Pressable, View, Stack, } from 'native-base'; import React, { Component } from 'react'; import { Dimensions } from 'react-native'; import { ListItem, SearchBar } from '@rneui/themed'; const windowWidth = Dimensions.get('window').width; class Ilegal extends Component { constructor(props) { super(props); this.state = { data: [], isLoading: true, isFetching: false, searchTxt: '', error: null, temp: [], }; }; async getData() { try { const response = await fetch( 'https://ojk-invest-api.vercel.app/api/illegals' ); const json = await response.json(); const illegalList = json.data.illegals; // 同时初始化data和temp为接口返回的数组 this.setState({ data: illegalList, temp: illegalList }); } catch (error) { console.error(error); this.setState({ error: error.message }); } finally { this.setState({ isLoading: false, isFetching: false, }); } }; renderHeader = () => { return <SearchBar placeholder='Cari Perusahaan..' lightTheme round editable={true} value={this.state.searchTxt} onChangeText={this.updateSearch} /> }; updateSearch = (searchTxt) => { this.setState({ searchTxt }, () => { if (!searchTxt.trim()) { // 搜索框为空时恢复原始数据 this.setState({ data: [...this.state.temp] }); return; } // 过滤并更新data状态 const filteredData = this.state.temp.filter(item => item.name.toLowerCase().includes(searchTxt.toLowerCase()) ).map(({ id, name, type }) => ({ id, name, type })); this.setState({ data: filteredData }); }); }; componentDidMount() { this.getData(); }; onRefresh = () => { this.setState({ isFetching: true }, () => { this.getData(); }); }; renderItem = ({ item }) => { const { navigation } = this.props; return ( <> <Pressable style={{ padding: 20, backgroundColor: 'white' }} onPress={() => navigation.navigate('Detail Ilegal', { data: item })}> <Center> <View style={{ flexDirection: 'column', justifyContent: 'center', alignItems: 'center', }}> <Text style={{ fontSize: 16, width: windowWidth - 40, textAlign: 'justify', marginTop: 6, }}> {item.name} </Text> <Text style={{ color: '#808080', fontSize: 14, width: windowWidth - 40, textAlign: 'justify', marginTop: 6, }}> {item.type} </Text> </View> </Center> </Pressable> <View style={{ borderWidth: 0.5, borderColor: '#cccccc' }}></View> </> ); }; render() { const { data, isLoading, isFetching, error} = this.state; return ( <View style={{ flex:1, justifyContent:'center', backgroundColor:'white', flexDirection: 'column', }}> {isLoading ? ( <Spinner size="large" color="#AA0002" /> ) : error ? ( <Text style={{ textAlign: 'center', padding: 20 }}>加载出错:{error}</Text> ) : ( <FlatList ListHeaderComponent={this.renderHeader} data={data} keyExtractor={(item) => item.id.toString()} renderItem={this.renderItem} onRefresh={this.onRefresh} refreshing={isFetching} /> )} </View> ); } } export default Ilegal;
内容的提问来源于stack exchange,提问作者Ramadhani A.R
相关产品推荐
相关产品推荐

