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

refactor(console): update react integration guide #6151

Merged
merged 3 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
167 changes: 73 additions & 94 deletions packages/console/src/assets/docs/guides/spa-react/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import InlineNotification from '@/ds-components/InlineNotification';
import Steps from '@/mdx-components/Steps';
import Step from '@/mdx-components/Step';

import Checkpoint from '../../fragments/_checkpoint.md';
import RedirectUrisWeb from '../../fragments/_redirect-uris-web.mdx';

<Steps>

<Step
Expand All @@ -19,28 +22,28 @@ npm i @logto/react
```

</TabItem>
<TabItem value="yarn" label="Yarn">
<TabItem value="pnpm" label="pnpm">

```bash
yarn add @logto/react
pnpm add @logto/react
```

</TabItem>
<TabItem value="pnpm" label="pnpm">
<TabItem value="yarn" label="yarn">

```bash
pnpm add @logto/react
yarn add @logto/react
```

</TabItem>
</Tabs>
</Step>

<Step title="Init LogtoClient">
<Step title="Init Logto provider">

Import and use `LogtoProvider` to provide a Logto context:
Import and use `LogtoProvider` to provide a Logto context to your app:

<Code className="language-tsx">
<Code className="language-tsx" title="App.tsx">
{`import { LogtoProvider, LogtoConfig } from '@logto/react';

const config: LogtoConfig = {
Expand All @@ -57,52 +60,19 @@ const App = () => (

</Step>

<Step
title="Implement sign-in"
subtitle="3 steps"
>

<InlineNotification>
In the following steps, we assume your app is running on <code>http://localhost:3000</code>.
</InlineNotification>

### Configure Redirect URI

First, let’s enter your redirect URI. E.g. `http://localhost:3000/callback`.
<Step title="Configure redirect URIs">

<UriInputField name="redirectUris" />
<RedirectUrisWeb />

### Implement a sign-in button

We provide two hooks `useHandleSignInCallback()` and `useLogto()` which can help you easily manage the authentication flow.

Go back to your IDE/editor, use the following code to implement the sign-in button:

<Code className="language-tsx">
{`import { useLogto } from '@logto/react';

const SignIn = () => {
const { signIn, isAuthenticated } = useLogto();

if (isAuthenticated) {
return <div>Signed in</div>;
}

return (
<button onClick={() => signIn('${props.redirectUris[0] ?? 'http://localhost:3000/callback'}')}>
Sign In
</button>
);
};`}
</Code>
</Step>

### Handle redirect
<Step title="Handle redirect">

We're almost there! In the last step, we use `http://localhost:3000/callback` as the Redirect URI, and now we need to handle it properly.
After the user signs in, Logto will redirect the user back to the redirect URI configured above. However, there are still things to do to make your application work properly.

First let's create a callback component:
First let's create a callback page:

```tsx
```tsx title="pages/Callback/index.tsx"
import { useHandleSignInCallback } from '@logto/react';

const Callback = () => {
Expand All @@ -114,90 +84,99 @@ const Callback = () => {
if (isLoading) {
return <div>Redirecting...</div>;
}

return null;
};
```

Finally insert the code below to create a `/callback` route which does NOT require authentication:
Then, insert the code below to create a `/callback` route which does NOT require authentication:

```tsx
```tsx title="App.tsx"
// Assuming react-router
<Route path="/callback" element={<Callback />} />
```

</Step>

<Step title="Implement sign-out">

Calling `.signOut()` will clear all the Logto data in memory and localStorage if they exist.
<Step title="Implement sign-in and sign-out">

After signing out, it'll be great to redirect user back to your website. Let's add `http://localhost:3000` as the Post Sign-out URI below, and use it as the parameter when calling `.signOut()`.
We provide a hook `useLogto()` which can help you easily manage the authentication flow.

<UriInputField name="postLogoutRedirectUris" />
<InlineNotification>
Before calling `.signIn()`, make sure you have correctly configured Redirect URI in Admin Console.
</InlineNotification>

### Implement a sign-out button
<Code className="language-tsx" title="pages/Home/index.tsx">
{`import { useLogto } from '@logto/react';

<Code className="language-tsx">
{`const SignOut = () => {
const { signOut } = useLogto();
const Home = () => {
const { signIn, signOut, isAuthenticated } = useLogto();

return (
<button onClick={() => signOut('${
props.postLogoutRedirectUris[0] ?? 'http://localhost:3000'
}')}>
Sign out
</button>
return isAuthenticated ? (
<button onClick={() => signOut('${props.postLogoutRedirectUris[0] ?? 'http://localhost:3000'}')}>Sign Out</button>
) : (
<button onClick={() => signIn('${props.redirectUris[0] ?? 'http://localhost:3000/callback'}')}>Sign In</button>
);
};`}
</Code>

Calling `.signOut()` will clear all the Logto data in memory and localStorage if they exist.

</Step>

<Step
title="Checkpoint: Test your application"
>

<Checkpoint />

</Step>

<Step title="Handle authentication status">
<Step title="Display user information">

In Logto SDK, generally we can use `logtoClient.isAuthenticated` to check the authentication status, if the user is signed in, the value will be `true`, otherwise, the value will be `false`.
To display the user's information, you can use the `getIdTokenClaims()` method. For example, in your Home page:

In Logto React SDK, the `isAuthenticated` status can be checked by using the `useLogto` hook. In the example code below, we can use it to programmatically show and hide the sign-in and sign-out buttons. And also use `getIdTokenClaims` to get the id of the currently logged-in user.
```tsx title="pages/Home/index.tsx"
import { useLogto, type IdTokenClaims } from '@logto/react';
import { useEffect, useState } from 'react';

```tsx
const Home = () => {
const { isAuthenticated, getIdTokenClaims, signIn, signOut } = useLogto();
const [userId, setUserId] = useState('');
const { isAuthenticated, getIdTokenClaims } = useLogto();
const [user, setUser] = useState<IdTokenClaims>();

useEffect(() => {
(async () => {
if (isAuthenticated) {
const claims = await getIdTokenClaims();
setUserId(claims.sub);
setUser(claims);
}
})();
}, [isAuthenticated]);
}, [getIdTokenClaims, isAuthenticated]);

return (
<div>
{userId && <p>Logged in as {userId}</p>}
{isAuthenticated ? (
<button onClick={signOut}>Sign Out</button>
) : (
<button onClick={() => signIn('http://localhost:3000/callback')}>Sign In</button>
)}
</div>
// ...
{isAuthenticated && user && (
<table>
<thead>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{Object.entries(user).map(([key, value]) => (
<tr key={key}>
<td>{key}</td>
<td>{typeof value === 'string' ? value : JSON.stringify(value)}</td>
</tr>
))}
</tbody>
</table>
)}
);
};
}
```

</Step>

<Step
title="Checkpoint: Test your application"
>

Now, you can test your application:

1. Run your application, you will see the sign-in button.
2. Click the sign-in button, the SDK will init the sign-in process and redirect you to the Logto sign-in page.
3. After you signed in, you will be redirected back to your application and see user ID and the sign-out button.
4. Click the sign-out button to sign-out.

</Step>

</Steps>
4 changes: 4 additions & 0 deletions packages/console/src/components/Guide/index.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@

hr {
border-color: var(--color-border);

+ div {
margin-top: _.unit(4.5);
}
}
}
}
Expand Down
Loading