You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 10:24:03