React Native:基于嵌套JSON实现技能搜索FlatList的问题求助
实现React Native中按技能搜索员工的FlatList
我帮你修改代码来实现技能搜索功能,核心思路是先把员工数据扁平化为每个技能对应一个条目,这样不管是搜索员工姓名还是技能名称,都能方便地过滤出匹配的结果。以下是修改后的完整代码:
// Searching using Search Bar Filter in React Native List View // import React in our code import React, { useState, useEffect } from "react"; // import all the components we are going to use import { SafeAreaView, Text, StyleSheet, View, FlatList, TextInput, Image, TouchableOpacity, } from "react-native"; // import employee json import employeeList from "../json/employee"; const AllListScreen = ({ navigation, route }) => { const [search, setSearch] = useState(""); const [filteredDataSource, setFilteredDataSource] = useState([]); const [masterDataSource, setMasterDataSource] = useState([]); // 初始化:将员工数据扁平化为「员工+技能」的条目数组 useEffect(() => { const flatSkillItems = employeeList.flatMap(employee => employee.skills.map(skill => ({ employee, skill })) ); setFilteredDataSource(flatSkillItems); setMasterDataSource(flatSkillItems); }, []); const searchFilterFunction = (text) => { if (text) { const upperSearchText = text.toUpperCase(); // 过滤匹配员工姓名 或 技能名称的条目 const newData = masterDataSource.filter(item => { const employeeName = item.employee.name.toUpperCase(); const skillName = item.skill.name.toUpperCase(); return employeeName.includes(upperSearchText) || skillName.includes(upperSearchText); }); setFilteredDataSource(newData); setSearch(text); } else { // 搜索为空时恢复全部数据 setFilteredDataSource(masterDataSource); setSearch(text); } }; const ItemView = ({ item }) => { const { employee, skill } = item; return ( <TouchableOpacity onPress={() => console.log(`选中技能:${skill.name}`)} style={styles.itemStyle} > <Image source={employee.image} // 使用员工自身的头像图片 style={{ height: 50, width: 50, borderRadius: 25 }} // 可选:添加圆角更美观 /> <View style={styles.textPortion}> <Text style={styles.employeeName}>{employee.name}</Text> <Text style={styles.skillName}>{skill.name.toUpperCase()}</Text> </View> </TouchableOpacity> ); }; const ItemSeparatorView = () => { return ( <View style={{ height: 0.5, width: "100%", backgroundColor: "#C8C8C8", }} /> ); }; return ( <SafeAreaView style={{ flex: 1 }}> <View style={styles.container}> <TextInput style={styles.textInputStyle} onChangeText={(text) => searchFilterFunction(text)} value={search} underlineColorAndroid="transparent" placeholder="搜索员工姓名或技能" /> <FlatList data={filteredDataSource} keyExtractor={(item) => `${item.employee.id}-${item.skill.id}`} // 用员工+技能的唯一组合作为key renderItem={ItemView} ItemSeparatorComponent={ItemSeparatorView} // 统一设置条目分隔符 /> </View> </SafeAreaView> ); }; const styles = StyleSheet.create({ container: { backgroundColor: "#FFFFFF", flex: 1, }, itemStyle: { flex: 1, padding: 8, flexDirection: "row", alignItems: "center", }, textInputStyle: { height: 50, borderWidth: 1, paddingLeft: 20, margin: 6, borderColor: "#009688", backgroundColor: "#FFFFFF", borderRadius: 5, }, textPortion: { flexWrap: "wrap", flexShrink: 1, marginLeft: 12, }, employeeName: { fontSize: 16, fontWeight: "500", }, skillName: { fontSize: 14, color: "#666", marginTop: 4, }, }); export default AllListScreen;
关键修改说明:
数据扁平化处理
原代码直接用员工数组作为数据源,现在我们通过flatMap将每个员工的技能拆分为独立条目,形成[{employee, skill}, ...]的结构,这样搜索时可以直接针对每个技能条目进行匹配,完美契合你"展示拥有对应技能的员工姓名(无需去重)"的需求。搜索逻辑升级
修改searchFilterFunction,同时检查员工姓名和技能名称是否包含搜索文本,支持双向搜索(既搜员工也搜技能),输入任意关键词都能得到精准结果。渲染优化
- 修正了头像图片的引用,现在使用员工自身的
image字段(原代码用了随机图) - 给FlatList设置
ItemSeparatorComponent来统一处理分隔符,避免原代码中最后一个条目多余的分隔线 - 用
员工id+技能id作为唯一key,彻底解决渲染时的key冲突问题
- 修正了头像图片的引用,现在使用员工自身的
样式细节优化
添加了员工姓名和技能名称的差异化样式,提升可读性;给头像添加圆角,让界面更美观友好。
这样修改后,你输入技能名称(比如"Cooking"),就会显示所有拥有该技能的员工条目;输入员工姓名(比如"John"),也能显示该员工的所有技能条目,完全满足你的需求。
内容的提问来源于stack exchange,提问作者Dof
相关产品推荐
相关产品推荐

