React Native useState状态更新异常:筛选功能失效问题求助
问题描述
从API获取如下格式的对象数组:
[{ "category_param": {"id": 2, "name": "sport"}, "id": 2, "isSelect": false, "name": "temperature" }, ......... { "category_param": {"id": 1, "name": "food"}, "id": 99, "isSelect": false, "name": "location" }]
通过useState将数据分别存入data(用于展示操作)和dataInit(存储原始未筛选数据):
const [data, setData] = useState([]); const [dataInit, setDataInit] = useState([]);
页面展示data正常,但点击筛选按钮(按category_param.id筛选)时出现异常:
筛选按钮代码:
<TouchableOpacity key={0} accessibilityRole="button" onPress={() => onPress('')} > <Text>All</Text> </TouchableOpacity> <TouchableOpacity key={2} accessibilityRole="button" onPress={() => onPress(2)} > <Text>Sport</Text> </TouchableOpacity> <TouchableOpacity key={1} accessibilityRole="button" onPress={() => onPress(1)} > <Text>Food</Text> </TouchableOpacity>
点击事件函数:
const onPress = id => { setData(dataInit); // Line #1 if (id === '') { setData(dataInit); // Line #2 return; } console.log('BEFORE TAB FILTER:::', data); // Line #3 let filtered = data(item => { return item.category_param.id === id; }); setData(filtered); // Line #4 console.log('filtered:::', filtered); // Line #5 };
问题表现:页面刚打开时点击Sport(id=2)或Food(id=1)按钮可正常筛选;点击All按钮能恢复原始数据。但先点击Sport再点击Food时,结果为空,此时Line#3打印的是上一次筛选后的data而非重置后的原始数据。需要实现每次点击筛选按钮都先将data重置为API返回的原始数据,再执行筛选逻辑。
解决方案
问题根源
React的setState是异步操作,Line#1的setData(dataInit)不会立即更新data变量的值。后续代码中直接使用data时,拿到的还是当前渲染周期的旧值(上一次筛选后的结果)。所以先点Sport再点Food时,是基于Sport筛选后的数据集去筛选Food分类,自然找不到匹配项,结果为空。
修复方法
直接基于dataInit(原始数据)进行筛选,无需先重置data再筛选,避免异步更新的问题:
修改后的onPress函数:
const onPress = id => { if (id === '') { setData(dataInit); return; } // 直接从原始数据dataInit中筛选,而非当前的data const filtered = dataInit.filter(item => { return item.category_param.id === id; }); setData(filtered); };
额外优化点
- 原代码中
let filtered = data(item => {...})存在语法错误,数组筛选需使用filter方法,而非直接调用数组变量。 - 移除了冗余的
setData(dataInit)调用,逻辑更简洁清晰。
修改后,每次筛选都基于原始数据执行,无论之前的筛选状态如何,都能得到正确的结果。
内容的提问来源于stack exchange,提问作者Evgeny Anisimov
相关产品推荐
相关产品推荐

