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

(DOCSP-33540): React Native: Update Connect to an App Services App with auth hooks #3176

Merged
merged 4 commits into from
Feb 9, 2024
Merged
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
5 changes: 5 additions & 0 deletions examples/react-native/v12/TestApp/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {ObjectModels} from './src/components/object-models/ObjectModels';
import {RelationshipExamples} from './src/components/relationships/RealmWrapper';
import {CompensatingWriteErrorHandling} from './src/components/errors/CompensatingWriteWrapper';
import {EncryptMetadata} from './src/components/encryption/EncryptMetadata';
import { AppWithAuthHook } from './src/components/app-services/use-app';

// Screens
import {HomeScreen} from './src/screens/HomeScreen';
Expand Down Expand Up @@ -79,6 +80,10 @@ function App(): JSX.Element {
name="Authentication"
component={AuthenticationScreen}
/>
<Drawer.Screen
name="AppWithAuthHook"
component={AppWithAuthHook}
/>
<Drawer.Screen name="Encryption">
{props => (
<EncryptMetadata
Expand Down
6 changes: 3 additions & 3 deletions examples/react-native/v12/TestApp/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ PODS:
- React-jsi (= 0.72.6)
- React-logger (= 0.72.6)
- React-perflogger (= 0.72.6)
- RealmJS (12.2.1):
- RealmJS (12.3.0):
- React
- RNGestureHandler (2.13.2):
- React-Core
Expand Down Expand Up @@ -764,7 +764,7 @@ SPEC CHECKSUMS:
React-runtimescheduler: f23e337008403341177fc52ee4ca94e442c17ede
React-utils: fa59c9a3375fb6f4aeb66714fd3f7f76b43a9f16
ReactCommon: dd03c17275c200496f346af93a7b94c53f3093a4
RealmJS: b36dae5c0def204602827884512252a320332c69
RealmJS: 4c52a15602e70b64cd9230b0a17a9c12741371f4
RNGestureHandler: bb86e378287f7713baf3ca205423eb8109790022
RNReanimated: ab2e96c6d5591c3dfbb38a464f54c8d17fb34a87
RNScreens: 85d3880b52d34db7b8eeebe2f1a0e807c05e69fa
Expand All @@ -774,4 +774,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 5f146ddb62f4ae63c85ec80898f0a94176f8ed53

COCOAPODS: 1.13.0
COCOAPODS: 1.12.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'react-native';
import React from 'react';
import {AppWithAuthHook} from './use-app';
import {render, screen, userEvent} from '@testing-library/react-native';
import '@testing-library/jest-dom';

test('App with auth hook', async () => {
render(<AppWithAuthHook />);

const user = userEvent.setup();

const logInButton = screen.queryByTestId('log-in');

if (logInButton) {
await user.press(logInButton);
}

const loggedInUserText = await screen.findByTestId('logged-in-user-id');
expect(loggedInUserText).not.toEqual(null);

const notYetLoggedIn = screen.queryByText('No one is logged in yet.');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. I wish we could use the findBy* for everything because we can await results, but as you probably noticed, you can't test a negative with them. If findBy* doesn't find what it wants, it errors the whole test. 😢

This does mean there could be edge cases where queryByText isn't in sync with the rendered UI (because it's not waiting to find UI elements). But this is a great use for it.


expect(notYetLoggedIn).not.toBeInTheDocument();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// :snippet-start: app-config-imports
import React from 'react';
import {AppProvider, UserProvider} from '@realm/react';
// :snippet-end:
// :snippet-start: import-use-app
// :uncomment-start:
//import React from 'react';
// :uncomment-end:
import {useApp} from '@realm/react';
// :snippet-end:
import {useAuth} from '@realm/react';
import {Text, View, Pressable, StyleSheet} from 'react-native';
import {APP_ID} from '../../../appServicesConfig';

// :snippet-start: app-config
export const AppWithAuthHook = () => {
return (
<View>
<AppProvider id={APP_ID}>
<UserProvider fallback={LogIn}>
<MyApp />
</UserProvider>
</AppProvider>
</View>
);
};
// :snippet-end:

const LogIn = () => {
const {logInWithAnonymous} = useAuth();

return (
<View>
<Text>No one is logged in yet.</Text>
<Pressable
testID="log-in"
style={styles.button}
onPress={logInWithAnonymous}>
<Text style={styles.buttonText}>Log in</Text>
</Pressable>
</View>
);
};

// :snippet-start: use-app
function MyApp() {
const app = useApp();
// Proceed to app logic...
// :remove-start:
return (
<Text testID="logged-in-user-id">"Logged in as user with ID: {app.currentUser?.id}"</Text>
);
// :remove-end:
}
// :snippet-end:

const styles = StyleSheet.create({
section: {
flex: 1,
marginTop: 8,
paddingVertical: 12,
alignItems: 'center',
},
textInput: {
backgroundColor: '#C5CAE9',
borderBottomWidth: StyleSheet.hairlineWidth,
marginVertical: 5,
},
inputGroup: {
width: '100%',
},
buttonGroup: {
flexDirection: 'row',
flexWrap: 'wrap',
marginVertical: 12,
paddingVertical: 8,
justifyContent: 'center',
alignItems: 'center',
},
button: {
backgroundColor: '#3F51B5',
borderWidth: StyleSheet.hairlineWidth,
borderColor: '#ffffff',
paddingVertical: 5,
paddingHorizontal: 8,
marginVertical: 5,
marginHorizontal: 8,
},
buttonText: {
color: '#ffffff',
textAlign: 'center',
},
});
1 change: 1 addition & 0 deletions examples/react-native/v12/TestApp/src/navigation/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type RootStackParamList = {
encryptionKey: ArrayBuffer;
};
Quickstart: undefined;
AppWithAuthHook: undefined;
};

export type SubscriptionStackParamList = {
Expand Down
1 change: 1 addition & 0 deletions examples/react-native/v12/TestApp/testSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');
// Suppress noisy warnings. Should probably investigate
// all warnings at some point.
global.console.warn = jest.fn();
global.console.error = jest.fn();

beforeEach(async () => {
// Close and remove all realms in the default directory.
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.. code-block:: typescript

import React from 'react';
import {AppProvider, UserProvider} from '@realm/react';
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.. code-block:: typescript

export const AppWithAuthHook = () => {
return (
<View>
<AppProvider id={APP_ID}>
<UserProvider fallback={LogIn}>
<MyApp />
</UserProvider>
</AppProvider>
</View>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.. code-block:: typescript

import React from 'react';
import {useApp} from '@realm/react';
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.. code-block:: typescript

function MyApp() {
const app = useApp();
// Proceed to app logic...
}
8 changes: 6 additions & 2 deletions source/sdk/react-native/api-reference/app-provider.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
AppProvider (@realm/react)
==========================

.. meta::
:description: Learn how to use the AppProvider ReactElement hooks to work with an App Services App.
:keywords: code example

.. facet::
:name: genre
:values: reference
Expand Down Expand Up @@ -646,8 +650,8 @@ useApp()
The ``useApp()`` hook provides access to a :js-sdk:`Realm.App <classes/App.html>`
instance.

.. literalinclude:: /examples/generated/react-native/ts/use-app.test.snippet.use-app.tsx
:language: typescript
.. include:: /examples/generated/react-native/v12/use-app.snippet.import-use-app.tsx.rst
.. include:: /examples/generated/react-native/v12/use-app.snippet.use-app.tsx.rst

*Returns*

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
Connect to an Atlas App Services App - React Native SDK
=======================================================

.. meta::
:description: Connect to Atlas App Services from the Atlas Device SDK. Specify configuration details to customize App access.
:keywords: code example

.. facet::
:name: genre
:values: reference

.. contents:: On this page
:local:
:backlinks: none
Expand All @@ -30,9 +38,11 @@ Configure the App Client
To set up your App client, pass the App ID string
to the ``id`` prop of the ``AppProvider``.
Wrap any components that need to access the App with the ``AppProvider``.
In this example, we wrap the :ref:`UserProvider <react-native-user-provider>`
in the ``AppProvider`` to authenticate a user.

.. literalinclude:: /examples/generated/react-native/ts/app-provider.test.snippet.app-provider.tsx
:language: typescript
.. include:: /examples/generated/react-native/v12/use-app.snippet.app-config-imports.tsx.rst
.. include:: /examples/generated/react-native/v12/use-app.snippet.app-config.tsx.rst

.. include:: /includes/multiple-app-client-details-and-app-config-cache.rst

Expand All @@ -42,11 +52,10 @@ Retrieve an Instance of the App Client
--------------------------------------

All components wrapped within an ``AppProvider`` can access the :js-sdk:`App <Realm.App.html>`
client with the ``useApp()`` hook. Using the App, you can authenticate users
and access App Services.
client with the ``useApp()`` hook.

.. literalinclude:: /examples/generated/react-native/ts/use-app.test.snippet.use-app.tsx
:language: typescript
.. include:: /examples/generated/react-native/v12/use-app.snippet.import-use-app.tsx.rst
.. include:: /examples/generated/react-native/v12/use-app.snippet.use-app.tsx.rst

.. _react-native-retrieve-client-outside-provider:

Expand Down
Loading