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

在react-apollo Query中使用变量的技术实现咨询

Working with Variables & Optimizing Data Mapping in Apollo Client's Query Component (React Native)

Hey there! Since you're already familiar with using the graphql HOC to fetch data in your React Native Home component, let's dive into how to handle variables and optimize data mapping when using Apollo Client's <Query> component (or the modern useQuery hook, which is even more convenient for function components).

1. Variable Configuration in the <Query> Component

First, let's adjust your query to explicitly declare variables—this is best practice and makes your query reusable across different components or contexts:

// Define your query with a variable declaration
const GET_NEARBY_STORIES = gql`
  query GetNearbyStories($geoHash: String!) {
    getStoriesNearbyByGeoHash(geoHash: $geoHash) {
      id
    }
  }
`;

The $geoHash: String! syntax tells Apollo we expect a required string variable named geoHash for this query.

Static Variables

If your variable is static (like your mockGeoHash), pass it directly via the variables prop:

import { Query } from 'react-apollo';

// Inside your Home component's render method
<Query
  query={GET_NEARBY_STORIES}
  variables={{ geoHash: mockGeoHash }}
>
  {({ loading, error, data }) => {
    // Handle loading/error states first
    if (loading) return <Text>Loading nearby stories...</Text>;
    if (error) return <Text>Oops! {error.message}</Text>;

    // Map data to your desired format
    const storiesNearby = data.getStoriesNearbyByGeoHash.map(story => ({ id: story.id }));
    return <StoryList stories={storiesNearby} />;
  }}
</Query>

Dynamic Variables

If you need to update the variable dynamically (e.g., based on user location or component state), pull it directly from your component's state or props:

// For class components
<Query
  query={GET_NEARBY_STORIES}
  variables={{ geoHash: this.state.userGeoHash }}
>
  {/* ... render prop logic ... */}
</Query>

// For function components (using useState)
const [userGeoHash, setUserGeoHash] = useState('8k');
<Query
  query={GET_NEARBY_STORIES}
  variables={{ geoHash: userGeoHash }}
>
  {/* ... render prop logic ... */}
</Query>

2. Optimizing Data Mapping

Let's make your data mapping more efficient, maintainable, and less prone to unnecessary re-renders:

Extract Mapping Logic to a Pure Function

Avoid repeating inline mapping logic by extracting it to a reusable pure function. This makes updates easier and keeps your component code clean:

// Reusable mapper function (can live in a utils file too!)
const mapStoryToListItem = (story) => ({
  id: story.id,
  // Add other fields here if you need them later
});

// Use it in your Query component
const storiesNearby = data.getStoriesNearbyByGeoHash.map(mapStoryToListItem);

Memoize Mapped Data to Prevent Unnecessary Re-renders

If you're using function components, use React's useMemo hook to cache the mapped array. This ensures the array reference only changes when the source data updates, preventing child components from re-rendering unnecessarily:

import { useMemo } from 'react';

// Inside the Query's render prop or useQuery hook
const storiesNearby = useMemo(() => {
  return data.getStoriesNearbyByGeoHash.map(mapStoryToListItem);
}, [data.getStoriesNearbyByGeoHash]); // Only re-run if the source array changes

Keep Queries Targeted

You're already doing this well, but it's worth emphasizing: only request the fields you need in your GraphQL query. This reduces data transfer size and eliminates the need to filter out unused fields during mapping.

Reuse Loading/Error States

Create a reusable wrapper component to avoid duplicating loading/error logic across your app. This cuts down on boilerplate and ensures consistent UI for all query-driven components:

const QueryWrapper = ({ query, variables, children }) => (
  <Query query={query} variables={variables}>
    {({ loading, error, data }) => {
      if (loading) return <LoadingSpinner />;
      if (error) return <ErrorBanner message={error.message} />;
      return children(data);
    }}
  </QueryWrapper>
);

// Usage in Home component
<QueryWrapper query={GET_NEARBY_STORIES} variables={{ geoHash: mockGeoHash }}>
  {(data) => {
    const storiesNearby = data.getStoriesNearbyByGeoHash.map(mapStoryToListItem);
    return <StoryList stories={storiesNearby} />;
  }}
</QueryWrapper>

3. Bonus: Use the useQuery Hook (Modern Approach)

For function components, Apollo's useQuery hook is more concise than the <Query> render prop component. Here's how to refactor your code to use it:

import { useQuery, gql } from '@apollo/client'; // Note: Newer Apollo versions use @apollo/client

const GET_NEARBY_STORIES = gql`
  query GetNearbyStories($geoHash: String!) {
    getStoriesNearbyByGeoHash(geoHash: $geoHash) {
      id
    }
  }
`;

const mapStoryToListItem = (story) => ({ id: story.id });

const Home = () => {
  const { loading, error, data } = useQuery(GET_NEARBY_STORIES, {
    variables: { geoHash: mockGeoHash },
  });

  if (loading) return <Text>Loading...</Text>;
  if (error) return <Text>Error: {error.message}</Text>;

  const storiesNearby = useMemo(() => 
    data.getStoriesNearbyByGeoHash.map(mapStoryToListItem), 
    [data.getStoriesNearbyByGeoHash]
  );

  return <StoryList stories={storiesNearby} />;
};

export default Home;

内容的提问来源于stack exchange,提问作者reggie3

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:06:22