FlatList在Axios请求新数据后未重新渲染的问题排查
问题描述
实现MyList组件,根据传入的date参数通过Axios请求接口数据,使用FlatList渲染内容。当父组件更新date并传递给MyList后,接口返回新数据且list状态已更新,但FlatList未重新渲染展示变化后的内容。已配置extraData={list},问题依旧。
注意:两次请求返回的数组元素数量、_id、name完全一致,仅somelist字段的值存在差异。
相关代码
MyList组件
const MyList = ({ date }) => { const [list, setList] = useState([]); useEffect(() => { const url = `https://some-service.com/list?date=${date}`; axios.get(url).then((res) => { setList(res.data.result); }); }, [date]); return ( <FlatList data={list} extraData={list} renderItem={({ item }) => (<RenderItem item={item} />)} keyExtractor={(item) => item._id} /> ); };
父组件
//...其他代码...// const [date, setDate] = useState(moment().format('YYYY-MM-DD')); return ( <View style={styles.container}> <View style={styles.dateSelector}> <DateSelector date={date} setDate={setDate} /> </View> <MyList date={date} /> </View> );
接口返回示例
日期2022-12-04的返回
{ "status": "Success", "result": [ { "_id": "638b3ddc1b11677f6202eb4c", "name": "John Doe", "somelist": [ { "date": "2022-12-04T00:00:00.000Z", "status": "good" } ] }, { "_id": "638b3ddc1b11677f6202eb4f", "name": "Pappu", "somelist": [ { "date": "2022-12-04T00:00:00.000Z", "status": "bla" } ] } // ...更多数据 ] }
日期2022-12-03的返回
{ "status": "Success", "result": [ { "_id": "638b3ddc1b11677f6202eb4c", "name": "John Doe", "somelist": [ { "date": "2022-12-03T00:00:00.000Z", "status": "bad" } ] }, { "_id": "638b3ddc1b11677f6202eb4f", "name": "Pappu", "somelist": [ { "date": "2022-12-04T00:00:00.000Z", "status": "good" } ] } // ...更多数据 ] }
问题原因
- FlatList复用机制:FlatList通过
keyExtractor生成的唯一key识别列表项,两次请求返回的列表项_id相同,FlatList会复用原有组件实例,不会触发重新渲染。 - 浅比较限制:若
RenderItem是用React.memo包裹的纯组件,React默认浅比较仅对比item的顶层属性(_id、name),不会深入嵌套的somelist字段,无法感知其变化。 - extraData局限性:虽配置
extraData={list}让FlatList感知到数据集合变化,但子组件未正确响应嵌套数据更新时,仍无法触发渲染。
解决方案
方案1:修改keyExtractor,加入date标识
将date与_id组合作为唯一key,让FlatList识别为新列表项:
keyExtractor={(item) => `${item._id}-${date}`}
方案2:让RenderItem正确响应嵌套数据变化
若RenderItem使用React.memo,自定义比较函数实现深比较:
// 可使用lodash的isEqual,或自行实现深比较 import { isEqual } from 'lodash'; const RenderItem = React.memo(({ item }) => { // 组件渲染逻辑 }, (prevProps, nextProps) => { // 深比较item是否完全一致,不一致则重新渲染 return isEqual(prevProps.item, nextProps.item); });
若不想引入lodash,可针对somelist关键字段做针对性比较:
const RenderItem = React.memo(({ item }) => { // 组件渲染逻辑 }, (prevProps, nextProps) => { const prevSublist = prevProps.item.somelist[0]; const nextSublist = nextProps.item.somelist[0]; return prevSublist.date === nextSublist.date && prevSublist.status === nextSublist.status; });
方案3:强制更新列表引用
设置list时通过展开运算符生成新数组,确保引用变化:
setList([...res.data.result]);
方案4:扩展extraData的依赖
将date也加入extraData,让FlatList更明确感知到依赖变化:
extraData={{ list, date }}
内容的提问来源于stack exchange,提问作者UTKARSH DEEPAK
相关产品推荐
相关产品推荐

