Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial reactotron-apollo-client #1303

Draft
wants to merge 18 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 17 additions & 13 deletions apps/example-app/app/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,18 @@ import { useFonts } from "expo-font"
import React from "react"
import { initialWindowMetrics, SafeAreaProvider } from "react-native-safe-area-context"
import * as Linking from "expo-linking"
import { useInitialRootStore } from "app/mobxStateTree"
import { useInitialRootStore } from "app/stores/mobxStateTree"
import { AppNavigator, useNavigationPersistence } from "app/navigators"
import { ErrorBoundary } from "app/screens/ErrorScreen/ErrorBoundary"
import * as storage from "app/utils/storage"
import { customFontsToLoad } from "app/theme"
import Config from "app/config"
import { GestureHandlerRootView } from "react-native-gesture-handler"
import { StatusBar, ViewStyle } from "react-native"
import { store } from "app/redux"
import { store } from "app/stores/redux"
import { Provider as ReduxProvider } from "react-redux"
import { ApolloProvider } from "@apollo/client"
import { client as apolloClient } from "app/stores/apollo"

export const NAVIGATION_PERSISTENCE_KEY = "NAVIGATION_STATE"

Expand Down Expand Up @@ -101,17 +103,19 @@ function App(props: AppProps) {
// otherwise, we're ready to render the app
return (
<ReduxProvider store={store}>
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
<ErrorBoundary catchErrors={Config.catchErrors}>
<GestureHandlerRootView style={$container}>
<AppNavigator
linking={linking}
initialState={initialNavigationState}
onStateChange={onNavigationStateChange}
/>
</GestureHandlerRootView>
</ErrorBoundary>
</SafeAreaProvider>
<ApolloProvider client={apolloClient}>
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
<ErrorBoundary catchErrors={Config.catchErrors}>
<GestureHandlerRootView style={$container}>
<AppNavigator
linking={linking}
initialState={initialNavigationState}
onStateChange={onNavigationStateChange}
/>
</GestureHandlerRootView>
</ErrorBoundary>
</SafeAreaProvider>
</ApolloProvider>
</ReduxProvider>
)
}
Expand Down
5 changes: 4 additions & 1 deletion apps/example-app/app/devtools/ReactotronConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import { ArgType } from "reactotron-core-client"
import { mst } from "reactotron-mst"
import apisaucePlugin from "reactotron-apisauce"
import { reactotronRedux } from "reactotron-redux"
import apolloPlugin from "reactotron-apollo-client"

import { clear } from "app/utils/storage"
import { goBack, resetRoot, navigate } from "app/navigators/navigationUtilities"

import { Reactotron } from "./ReactotronClient"
import { client } from "../stores/apollo" // <--- update this location

const reactotron = Reactotron.configure({
name: require("../../package.json").name,
Expand All @@ -29,8 +31,9 @@ const reactotron = Reactotron.configure({
mst({
/** ignore some chatty `mobx-state-tree` actions */
filter: (event) => /postProcessSnapshot|@APPLY_SNAPSHOT/.test(event.name) === false,
}),
})
)
.use(apolloPlugin({ apolloClient: client }))

if (Platform.OS !== "web") {
reactotron.setAsyncStorageHandler?.(AsyncStorage)
Expand Down
11 changes: 11 additions & 0 deletions apps/example-app/app/navigators/AppNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ export type AppStackParamList = {
MobxStateTree: undefined
AsyncStorage: undefined
Redux: undefined
Apollo: undefined
ApolloDetail: {
item: {
__typename: string
id: number
number: number | null
title: string
}
}
}

/**
Expand Down Expand Up @@ -103,6 +112,8 @@ const AppStack = function AppStack() {
options={{ title: "Async Storage" }}
/>
<Stack.Screen name="Redux" component={Screens.ReduxScreen} />
<Stack.Screen name="Apollo" component={Screens.ApolloScreen} />
<Stack.Screen name="ApolloDetail" component={Screens.ApolloDetailScreen} />
</Stack.Group>
</Stack.Navigator>
)
Expand Down
99 changes: 99 additions & 0 deletions apps/example-app/app/screens/ApolloDetailScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import React from "react"
import { FlatList, TextStyle, View, ViewStyle } from "react-native"
import { ListItem, Text } from "app/components"
import { AppStackScreenProps } from "app/navigators"
import { colors, spacing } from "app/theme"
import { useSafeAreaInsetsStyle } from "app/utils/useSafeAreaInsetsStyle"
import { gql, useQuery } from "@apollo/client"
import { observer } from "mobx-react-lite"

const SECTIONS_QUERY = gql`
query Sections($id: Int!) {
chapter(id: $id) {
sections {
number
title
}
}
}
`

interface Section {
number: number
title: string
}

interface SectionItemProps {
chapter: {
__typename: string
id: number
number: number | null
title: string
}
section: Section
onPress?: () => void
}

const SectionItem: React.FC<SectionItemProps> = ({ chapter, section, onPress }) => (
<ListItem
text={`${chapter.number}.${section.number}: ${section.title}`}
onPress={onPress}
containerStyle={{ paddingHorizontal: spacing.sm }}
/>
)

interface ApolloDetailScreenProps extends AppStackScreenProps<"ApolloDetail"> {}

export const ApolloDetailScreen: React.FC<ApolloDetailScreenProps> = observer(
function ApolloScreen({ route }) {
const id = route.params.item.id

const { data, loading } = useQuery(SECTIONS_QUERY, {
variables: { id },
})

const $bottomContainerInsets = useSafeAreaInsetsStyle(["bottom"])

return (
<FlatList
style={$container}
contentContainerStyle={$bottomContainerInsets}
data={loading ? [] : data.chapter.sections}
renderItem={({ item }) => <SectionItem section={item} chapter={route.params.item} />}
ListHeaderComponent={() => {
return (
<View>
<Text
text="Reactotron can intercept and inspect Apollo client queries"
style={$subheading}
preset="subheading"
/>
<Text text="Like this example from the GraphQL example app:" style={$subheading} />
<View style={$bottomBorder} />
</View>
)
}}
keyExtractor={(section) => section.number.toString()}
/>
)
}
)

const $container: ViewStyle = {
flex: 1,
backgroundColor: colors.background,
}

const $text: TextStyle = {
color: colors.text,
}
const $subheading: TextStyle = {
...$text,
margin: spacing.sm,
}

const $bottomBorder: ViewStyle = {
borderBottomWidth: 1,
borderBottomColor: colors.text,
marginHorizontal: spacing.sm,
}
99 changes: 99 additions & 0 deletions apps/example-app/app/screens/ApolloScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import React from "react"
import { FlatList, TextStyle, View, ViewStyle } from "react-native"
import { ListItem, Text } from "app/components"
import { AppStackScreenProps } from "app/navigators"
import { colors, spacing } from "app/theme"
import { useSafeAreaInsetsStyle } from "app/utils/useSafeAreaInsetsStyle"
import { gql, useQuery } from "@apollo/client"
import { useNavigation } from "@react-navigation/native"
import { observer } from "mobx-react-lite"

const CHAPTERS_QUERY = gql`
query Chapters {
chapters {
id
number
title
}
}
`

const ChapterItem = ({
chapter,
onPress,
}: {
chapter: { id: number; number: number; title: string }
onPress?: () => void
}) => {
const { number, title } = chapter
let header, subheader

if (number) {
header = `Chapter ${number}`
subheader = ` - ${title}`
} else {
header = title
subheader = ""
}

return (
<ListItem
text={`${header}${subheader}`}
onPress={onPress}
containerStyle={{ paddingHorizontal: spacing.sm }}
/>
)
}

interface ApolloScreenProps extends AppStackScreenProps<"Apollo"> {}

export const ApolloScreen: React.FC<ApolloScreenProps> = observer(function ApolloScreen() {
const { data, loading } = useQuery(CHAPTERS_QUERY)
const navigation = useNavigation()

const $bottomContainerInsets = useSafeAreaInsetsStyle(["bottom"])

return (
<FlatList
style={$container}
contentContainerStyle={$bottomContainerInsets}
data={loading ? [] : data.chapters}
renderItem={({ item }) => (
<ChapterItem chapter={item} onPress={() => navigation.navigate("ApolloDetail", { item })} />
)}
ListHeaderComponent={() => {
return (
<View>
<Text
text="Reactotron can intercept and inspect Apollo client queries"
style={$subheading}
preset="subheading"
/>
<Text text="Like this example from the GraphQL example app:" style={$subheading} />
<View style={$bottomBorder} />
</View>
)
}}
keyExtractor={(chapter) => chapter.id.toString()}
/>
)
})

const $container: ViewStyle = {
flex: 1,
backgroundColor: colors.background,
}

const $text: TextStyle = {
color: colors.text,
}
const $subheading: TextStyle = {
...$text,
margin: spacing.sm,
}

const $bottomBorder: ViewStyle = {
borderBottomWidth: 1,
borderBottomColor: colors.text,
marginHorizontal: spacing.sm,
}
4 changes: 2 additions & 2 deletions apps/example-app/app/screens/ErrorGeneratorScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { useDispatch } from "react-redux"
import { Button, Text } from "app/components"
import type { AppStackScreenProps } from "app/navigators"
import { colors, spacing } from "app/theme"
import type { AppDispatch } from "app/redux"
import { throwAnError, throwErrorAsync } from "app/redux/errorSlice"
import type { AppDispatch } from "app/stores/redux"
import { throwAnError, throwErrorAsync } from "app/stores/redux/errorSlice"
import { useSafeAreaInsetsStyle } from "app/utils/useSafeAreaInsetsStyle"

interface ErrorGeneratorScreenProps extends AppStackScreenProps<"ErrorGenerator"> {}
Expand Down
2 changes: 1 addition & 1 deletion apps/example-app/app/screens/MobxStateTreeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ScrollView, TextStyle, View, ViewStyle } from "react-native"
import { Button, Text } from "app/components"
import { AppStackScreenProps } from "app/navigators"
import { colors, spacing } from "app/theme"
import { useStores } from "app/mobxStateTree"
import { useStores } from "app/stores/mobxStateTree"
import { Repo } from "app/components/Repo"
import { useSafeAreaInsetsStyle } from "app/utils/useSafeAreaInsetsStyle"

Expand Down
6 changes: 3 additions & 3 deletions apps/example-app/app/screens/ReduxScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { Button, Text } from "app/components"
import { Repo } from "app/components/Repo"
import { AppStackScreenProps } from "app/navigators"
import { colors, spacing } from "app/theme"
import type { AppDispatch, RootState } from "app/redux"
import { fetchAsync, reset as repoReset } from "app/redux/repoSlice"
import { changeSize, changeSpeed, reset as logoReset } from "app/redux/logoSlice"
import type { AppDispatch, RootState } from "app/stores/redux"
import { fetchAsync, reset as repoReset } from "app/stores/redux/repoSlice"
import { changeSize, changeSpeed, reset as logoReset } from "app/stores/redux/logoSlice"
import { useSafeAreaInsetsStyle } from "app/utils/useSafeAreaInsetsStyle"

interface ReduxScreenProps extends AppStackScreenProps<"Redux"> {}
Expand Down
6 changes: 6 additions & 0 deletions apps/example-app/app/screens/WelcomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ export const WelcomeScreen: React.FC<WelcomeScreenProps> = function WelcomeScree
navigation.navigate("Redux")
}}
/>
<ListItem
text="Apollo Client"
onPress={() => {
navigation.navigate("Apollo")
}}
/>
</View>
</ScrollView>
</SafeAreaView>
Expand Down
2 changes: 2 additions & 0 deletions apps/example-app/app/screens/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export * from "./MobxStateTreeScreen"
export * from "./ReduxScreen"
export * from "./ErrorGeneratorScreen"
export * from "./AsyncStorageScreen"
export * from "./ApolloScreen"
export * from "./ApolloDetailScreen"

export * from "./ErrorScreen/ErrorBoundary"
// export other screens here
9 changes: 9 additions & 0 deletions apps/example-app/app/stores/apollo/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ApolloClient, InMemoryCache } from "@apollo/client"

const cache = new InMemoryCache()

export const client = new ApolloClient({
uri: "https://api.graphql.guide/graphql",
cache,
defaultOptions: { watchQuery: { fetchPolicy: "cache-and-network" } },
})
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/
import { applySnapshot, IDisposer, onSnapshot } from "mobx-state-tree"
import { RootStore, RootStoreSnapshot } from "../RootStore"
import * as storage from "../../utils/storage"
import * as storage from "app/utils/storage"

/**
* The key we'll be saving our state as within async storage.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { configureStore } from "@reduxjs/toolkit"
import type { GetDefaultEnhancers } from "@reduxjs/toolkit/dist/getDefaultEnhancers"
import logoReducer from "../redux/logoSlice"
import repoReducer from "../redux/repoSlice"
import errorReducer from "../redux/errorSlice"
import logoReducer from "./logoSlice"
import repoReducer from "./repoSlice"
import errorReducer from "./errorSlice"

const createEnhancers = (getDefaultEnhancers: GetDefaultEnhancers<any>) => {
if (__DEV__) {
const reactotron = require("../devtools/ReactotronConfig").default
const reactotron = require("../../devtools/ReactotronConfig").default
return getDefaultEnhancers().concat(reactotron.createEnhancer())
} else {
return getDefaultEnhancers()
Expand Down
Loading