React Native中如何触发Flatlist重新渲染并将useEffect更新数据传递给renderItem
核心问题修复步骤
1. 修复Apollo Client重复实例化问题
你把Apollo Client的创建逻辑写在了App组件内部,App组件每次重渲染都会生成新的client实例,之前缓存的分页数据会被完全清空,这是FlatList始终只能拿到第一页数据的核心原因。
将client的创建逻辑移到App组件外部,或者用useMemo缓存:
// App.tsx 中将client移出组件,或者用useMemo包裹 const client = new ApolloClient({ cache: new InMemoryCache(), link: ApolloLink.from([errorLink, uploadLink as unknown as ApolloLink]), }); const App: () => Node = () => { // 原有组件逻辑不变,移除内部的client创建代码 }
如果errorLink和uploadLink需要依赖组件内的accessToken,可以用useMemo缓存client:
const App: () => Node = () => { // ...原有state声明不变 const client = useMemo(() => { const errorLink = onError(({ graphQLErrors, operation, forward }) => { if (graphQLErrors) { for (const err of graphQLErrors) { if (err.extensions?.code === "UNAUTHENTICATED") { operation.setContext({ headers: { ...operation.getContext().headers, authorization: `Bearer ${getAccessToken(setAccessToken)}`, }, }); return forward(operation); } } } }); const uploadLink = createUploadLink({ uri: "https://backend03-team.codebootcamp.co.kr/team05", headers: { authorization: `Bearer ${accessToken}`, }, credentials: "include", }); return new ApolloClient({ cache: new InMemoryCache(), link: ApolloLink.from([errorLink, uploadLink as unknown as ApolloLink]), }); }, [accessToken]) // 仅当accessToken变化时才重新创建client // ...原有return逻辑不变 }
2. 修复ListContainer的useEffect依赖与变量顺序
- 把useContext声明移到useEffect前面,确保useEffect能拿到最新的tagId
- 把tagId添加到useEffect依赖数组,切换标签时能重新触发校验逻辑
// ListContainer.tsx 调整代码顺序 const { setId, id, setTagId, tagId } = useContext(GlobalContext); // 移到useEffect前面 useEffect(() => { // ...原有校验逻辑不变 }, [data?.fetchUseditems, tagId]) // 新增tagId依赖
3. 修复FlatList渲染配置
- 修正keyExtractor的取值,你业务代码里用的是
_id,之前写的item.id拿不到正确的唯一键,会导致FlatList复用旧Item不更新 - 修正extraData配置,把renderItem用到的tagId也加进去,确保tag切换或者数据更新时FlatList会重新渲染
// presenter层ListUI组件的FlatList修改为: <FlatList data={props.data?.fetchUseditems ?? []} renderItem={renderItem} keyExtractor={(item) => item._id} // 修正为_id onEndReached={props.onLoadMore} extraData={[props.data, tagId]} // 新增tagId到extraData onEndReachedThreshold={0.8} />
4. 修复fetchMore的闭包问题
onLoadMore里计算页码用的是当前闭包的旧data值,多次连续加载时页码计算会出错,改为从updateQuery里获取最新的列表长度计算:
const onLoadMore = () => { fetchMore({ variables: { page: 1, // 这里可传占位值,实际页码可在updateQuery里基于现有列表长度计算 }, updateQuery: (prev, { fetchMoreResult }) => { if (!fetchMoreResult) return prev; return { fetchUseditems: [ ...prev.fetchUseditems, ...fetchMoreResult.fetchUseditems, ], }; }, }); };
内容的提问来源于stack exchange,提问作者sangki
相关产品推荐
相关产品推荐

