0

I thought that relay modern implemented a system whereby it would not try to fetch data until it was rendering the component that declared it. I am talking about fragment components. I have tried to test this but it is fetching all the data.

import React from "react";
import { Environment, Network, RecordSource, Store } from "relay-runtime";
import {
  RelayEnvironmentProvider,
} from "react-relay/hooks";
import "./App.css";
import QueryLoaderComponent from "./QueryLoaderComponent";
import QueryComponent from "./QueryComponent";

async function fetchGraphQL(text: string, variables: Record<any, any>) {

  // Fetch data from GitHub's GraphQL API:
  const response = await fetch("https://countries.trevorblades.com/", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      query: text,
      variables,
    }),
  });

  // Get the response as JSON
  return await response.json();
}

async function fetchRelay(params: any, variables: any) {
  console.log(
    `fetching query ${params.name} with ${JSON.stringify(variables)}`
  );
  return fetchGraphQL(params.text, variables);
}

// Export a singleton instance of Relay Environment configured with our network function:
const environment = new Environment({
  network: Network.create(fetchRelay),
  store: new Store(new RecordSource()),
});

function App() {
  
  return (
    <RelayEnvironmentProvider environment={environment}>
      {/* <QueryLoaderComponent /> */}
      <QueryComponent />
    </RelayEnvironmentProvider>
  );
}

export default App;
import { useState } from "react";
// @ts-ignore
import graphql from "babel-plugin-relay/macro";
import { QueryComponentQuery } from "./__generated__/QueryComponentQuery.graphql";
import { PreloadedQuery, useLazyLoadQuery, usePreloadedQuery } from "react-relay";
// import FragmentComponent from "./FragmentComponent";

const query = graphql`
  query QueryComponentQuery($id: ID!) {
    country(code: $id) {
      name
      ...FragmentComponent_country
    }
  }
`;

interface Props {
  // queryRef: PreloadedQuery<QueryComponentQuery>;
}

const QueryComponent = ({
  // queryRef
}: Props) => {
  const data = useLazyLoadQuery<QueryComponentQuery>(query, { id: "US"});
  const [showContinent, setShowContinent] = useState(false);
  return (
    <div>
      <button onClick={() => setShowContinent(!showContinent)}>
        {showContinent ? "Hide" : "Show"} continent
      </button>
      <h1>{data.country?.name}</h1>
      {/* <ul>
        {data.countries.map((country: any) => (
          <li key={country.name}>
            {country.name}{" "}
            {showContinent && <FragmentComponent country={country} />}
          </li>
        ))}
      </ul> */}
    </div>
  );
};

export default QueryComponent;
import { useFragment } from "react-relay";
// @ts-ignore
import graphql from "babel-plugin-relay/macro";
import { FragmentComponent_country$key } from "./__generated__/FragmentComponent_country.graphql";

export const fragment = graphql`
  fragment FragmentComponent_country on Country {
    continent {
      name
    }
  }
`;

interface Props {
  country: FragmentComponent_country$key;
}

const FragmentComponent = ({ country }: Props) => {
  const data = useFragment(fragment, country);
  return <div>{data.continent.name}</div>;
};

export default FragmentComponent;

this is fetching the data for the fragment component even though it is not rendering the fragment component. is there a way to defer it until it is rendering the component?

Joey Gough
  • 2,753
  • 2
  • 21
  • 42

1 Answers1

0

use

React Suspense

on the fragment or anywhere where fetching happens as wrapper

gpbaculio
  • 5,693
  • 13
  • 60
  • 102