diff --git a/with-apollo/App.js b/with-apollo/App.js
index 87d36477..43c036bc 100644
--- a/with-apollo/App.js
+++ b/with-apollo/App.js
@@ -1,46 +1,50 @@
-import { ApolloProvider, gql, useQuery } from "@apollo/client";
+import { gql } from "@apollo/client";
+import { ApolloProvider, useQuery } from "@apollo/client/react";
import { Picker } from "@react-native-picker/picker";
-import { useState } from "react";
+import { useState, useEffect } from "react";
import { ActivityIndicator, StyleSheet, Text, View } from "react-native";
-
import { apolloClient } from "./apollo";
-// Imperial I-class Star Destroyer
-const defaultStarshipId = "c3RhcnNoaXBzOjM=";
+// Imperial I-class Star Destroyer (numeric ID string, not Relay)
+const defaultStarshipId = "3";
-const LIST_STARSHIPTS = gql`
+// List all starships (your wrapper returns results array)
+const LIST_STARSHIPS = gql`
query listStarships {
allStarships {
- starships {
- id
- name
+ edges {
+ node {
+ id
+ name
+ }
}
}
}
`;
+// Fetch single starship by numeric id (snake_case + films = [String])
const GET_STARSHIP = gql`
query getStarship($id: ID!) {
- starship(id: $id) {
+ starshipById(id: $id) {
id
name
model
- starshipClass
- manufacturers
- length
+ starship_class
crew
- costInCredits
+ length
+ cost_in_credits
consumables
- filmConnection {
- films {
- id
- title
- }
+ manufacturers
+ film_names {
+ title
+ episode_id
+ release_date
}
}
}
`;
+
function RootComponent() {
const [starshipId, setStarshipId] = useState(defaultStarshipId);
const { data, error, loading } = useQuery(GET_STARSHIP, {
@@ -51,6 +55,8 @@ function RootComponent() {
console.log("Error fetching starship", error);
}
+ const starship = data?.starshipById;
+
return (
@@ -59,24 +65,33 @@ function RootComponent() {
onStarshipChange={setStarshipId}
/>
- {loading ? (
-
- ) : (
-
- )}
+
+ {loading ? (
+
+ ) : starship ? (
+
+ ) : (
+ No starship found
+ )}
+
);
}
function StarshipPicker(props) {
- const { data, error, loading } = useQuery(LIST_STARSHIPTS);
+ const { data, error, loading } = useQuery(LIST_STARSHIPS);
if (error) {
console.log("Error listing starships", error);
+ return Failed to load starships;
}
- if (loading) return null;
- const { starships } = data.allStarships;
+ if (loading) {
+ return null;
+ }
+
+ // Flatten edges → nodes
+ const starships = data.allStarships.edges.map(edge => edge.node);
return (
@@ -104,29 +123,48 @@ function StarshipDetails({ starship }) {
Operational abilities
- - {starship.crew} crew members
- - {starship.consumables} without restocking
+ - {starship.crew ?? "N/A"} crew members
+ - {starship.consumables ?? "N/A"} without restocking
-
+
Ship attributes
- - {starship.length}m long
- - {starship.costInCredits} credits
+ - {starship.length ?? "N/A"}m long
+ - {starship.cost_in_credits ?? "N/A"} credits
-
- Manufacturers
- {starship.manufacturers.map((manufacturer) => (
- - {manufacturer}
- ))}
-
+ {starship.manufacturers?.length > 0 && (
+
+ Manufacturers
+ {starship.manufacturers.map((m, idx) => (
+ - {m}
+ ))}
+
+ )}
-
- Appeared in
- {starship.filmConnection.films.map((film) => (
- - {film.title}
- ))}
-
+ {starship.film_names?.length > 0 && (
+
+ Appeared in
+ {starship.film_names.map((film, idx) => (
+
+ - {film.title} (Episode {film.episode_id}, {film.release_date})
+
+ ))}
+
+ )}
+
+ {loadingFilms ? (
+
+ ) : films.length > 0 ? (
+
+ Appeared in
+ {films.map((film, idx) => (
+
+ - {film.title} (Episode {film.episode_id})
+
+ ))}
+
+ ) : null}
>
);
}
@@ -136,11 +174,18 @@ const styles = StyleSheet.create({
flex: 1,
justifyContent: "center",
alignItems: "center",
+ },
+ detailsContainer: {
+ flexGrow: 1,
+ justifyContent: "flex-start", // keeps it pinned to the top
+ minHeight: 200, // avoids collapse
+ paddingTop: 20,
},
container: {
flex: 1,
justifyContent: "center",
paddingHorizontal: 50,
+ paddingTop: 100,
},
label: {
marginBottom: 2,
diff --git a/with-apollo/README.md b/with-apollo/README.md
index e970c339..4ff7b45d 100644
--- a/with-apollo/README.md
+++ b/with-apollo/README.md
@@ -22,4 +22,4 @@
- The Apollo configuration lies in the `apollo.js` file.
- The file also contains an option (with commented code) to pass an authorization token to the API.
-- [Apollo Client Docs](https://www.apollographql.com/docs/react/v3.0-beta/)
+- [Apollo Client Docs](https://www.apollographql.com/docs/react/get-started/)
diff --git a/with-apollo/apollo.js b/with-apollo/apollo.js
index b0274156..783cc4a4 100644
--- a/with-apollo/apollo.js
+++ b/with-apollo/apollo.js
@@ -1,8 +1,9 @@
import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client';
-// import { setContext } from '@apollo/link-context';
+// import { ApolloProvider, ApolloLink } from '@apollo/client';
+
// see: https://github.com/graphql/swapi-graphql
-const GRAPHQL_API_URL = 'https://swapi-graphql.netlify.app/.netlify/functions/index';
+const GRAPHQL_API_URL = 'https://swapi-gql-wrapper.vercel.app/api/graphql';
/*
uncomment the code below in case you are using a GraphQL API that requires some form of
@@ -11,12 +12,15 @@ you provide while making the request.
const TOKEN = '';
-const asyncAuthLink = setContext(async () => {
- return {
+
+const authLink = new ApolloLink((operation, forward) => {
+ operation.setContext(({ headers = {} }) => ({
headers: {
- Authorization: TOKEN,
+ ...headers,
+ Authorization: TOKEN ? `Bearer ${TOKEN}` : '',
},
- };
+ }));
+ return forward(operation);
});
*/
@@ -28,5 +32,5 @@ const httpLink = new HttpLink({
export const apolloClient = new ApolloClient({
cache: new InMemoryCache(),
link: httpLink,
- // link: asyncAuthLink.concat(httpLink),
-});
+ // link: authLink.concat(httpLink),
+});
\ No newline at end of file
diff --git a/with-apollo/package.json b/with-apollo/package.json
index 4d5fda0a..136b71f7 100644
--- a/with-apollo/package.json
+++ b/with-apollo/package.json
@@ -1,13 +1,12 @@
{
"dependencies": {
- "@apollo/client": "^3.4.16",
- "@apollo/link-context": "^2.0.0-beta.3",
- "@react-native-picker/picker": "2.11.1",
- "expo": "^54.0.1",
- "graphql": "^15.0.0",
- "react": "19.1.0",
- "react-dom": "19.1.0",
- "react-native": "0.81.4",
- "react-native-web": "^0.21.0"
+ "@apollo/client": "^4.0.4",
+ "@react-native-picker/picker": "latest",
+ "expo": "^54.0.1",
+ "graphql": "^16.11.0",
+ "react": "19.1.0",
+ "react-dom": "19.1.0",
+ "react-native": "0.81.4",
+ "react-native-web": "latest"
}
}