All libraries and documentation are currently in Beta. Content and features are subject to change.

Sample Application

The following outlines how a sample application uses the Inrupt’s Solid React SDK to log in to a user’s Pod and displays the Profile. The sample application allows users to view/edit user profile. You can play with the application at https://solid-ui-react-example.docs.inrupt.com/.

Session Provider

The sample application uses the SessionProvider and wraps the application in the SessionProvider

import { SessionProvider } from "@inrupt/solid-ui-react";

/* eslint react/jsx-props-no-spreading: 0 */

interface IApp {
  Component: React.ComponentType<any>;
  pageProps: any;
}

export default function App(props: IApp): React.ReactElement {
  const { Component, pageProps } = props;

  return (
    <SessionProvider sessionId="react-sdk-example-project">
      <Component {...pageProps} />
    </SessionProvider>
  );
}

(Source: pages/_app.tsx)

Session and Login Status

Wrapped within the SessionProvider, the sample application can use the Inrupt SDK’s useSession interface to access the current Session and check its login status.

import { useSession } from "@inrupt/solid-ui-react/dist";
import LoginForm from "../components/loginForm";
import Profile from "../components/profile";

export default function Home(): React.ReactElement {
  const { session } = useSession();

  if (!session.info.isLoggedIn) {
    return <LoginForm />;
  }

(Source: pages/index.tsx)

Log In

To log in, sample application creates a LoginForm that uses Inrupt SDK’s LoginButton. Specify the oidcIssuer and redirectUrl attributes for the LoginButton:

import { useState, useEffect } from "react";
import { LoginButton } from "@inrupt/solid-ui-react";
import { Button, TextField, FormGroup, Container } from "@material-ui/core";

export default function LoginForm(): React.ReactElement {
  const [idp, setIdp] = useState("https://inrupt.net");
  const [currentUrl, setCurrentUrl] = useState("https://localhost:3000");

  useEffect(() => {
    setCurrentUrl(window.location.href);
  }, [setCurrentUrl]);

  return (
    <Container fixed>
      <FormGroup>
        <TextField
          label="Identity Provider"
          placeholder="Identity Provider"
          type="url"
          value={idp}
          onChange={(e) => setIdp(e.target.value)}
          InputProps={{
            endAdornment: (
              <LoginButton oidcIssuer={idp} redirectUrl={currentUrl}>
                <Button variant="contained" color="primary">
                  Log&nbsp;in
                </Button>
              </LoginButton>
            ),
          }}
        />
      </FormGroup>
    </Container>
  );
}

(Source: components/loginForm/index.tsx)

You can also specify an optional onError attributes for the LoginButton.

Display the Profile

The sample application uses the Inrupt SDK’s to display the profile data:

  • The CombinedDataProvider specifies the URL of the profile SolidDataset.

  • The following Inrupt SDK components display various properties from the profile. The components provide an edit attribute to toggle these fields to be editable or non-editable. You can also specify the autosave attribute.

import { useState } from "react";

import {
  useSession,
  CombinedDataProvider,
  Image,
  LogoutButton,
  Text,
  Value,
} from "@inrupt/solid-ui-react";

import {
  Box,
  Button,
  Card,
  CardActions,
  CardActionArea,
  CardContent,
  Container,
  Typography,
} from "@material-ui/core";

import BusinessIcon from "@material-ui/icons/Business";

import { FOAF, VCARD } from "@inrupt/lit-generated-vocab-common";

import ContactTable from "../contactTable";

export default function LoginForm(): React.ReactElement {
  const { session } = useSession();
  const { webId } = session.info;
  const [editing, setEditing] = useState(false);

  return (
    <Container fixed>
      <Box style={{ marginBottom: 16, textAlign: "right" }}>
        <LogoutButton>
          <Button variant="contained" color="primary">
            Log&nbsp;out
          </Button>
        </LogoutButton>
      </Box>
      <CombinedDataProvider datasetUrl={webId} thingUrl={webId}>
        <Card style={{ maxWidth: 480 }}>
          <CardActionArea
            style={{
              justifyContent: "center",
              display: "flex",
            }}
          >
            <Image property={VCARD.hasPhoto.iri.value} width={480} />
          </CardActionArea>

          <CardContent>
            <Typography gutterBottom variant="h5" component="h2">
              <Text property={FOAF.name.iri.value} edit={editing} autosave />
            </Typography>

            <Typography
              variant="body2"
              color="textSecondary"
              component="p"
              style={{
                display: "flex",
                alignItems: "center",
              }}
            >
              <BusinessIcon />

              <Text
                property={VCARD.organization_name.iri.value}
                edit={editing}
                autosave
              />
            </Typography>

            <Typography variant="body2" color="textSecondary" component="p">
              {"Born: "}
              <Value
                property={VCARD.bday.iri.value}
                dataType="datetime"
                edit={editing}
                autosave
              />
            </Typography>
          </CardContent>

          <CardContent>
            <Typography gutterBottom variant="h6" component="h3">
              Email Addresses
            </Typography>

            <ContactTable property={VCARD.hasEmail.value} edit={editing} />
          </CardContent>

          <CardContent>
            <Typography gutterBottom variant="h6" component="h3">
              Phone Numbers
            </Typography>

            <ContactTable property={VCARD.hasTelephone.value} edit={editing} />
          </CardContent>

          <CardActions>
            <Button
              size="small"
              color="primary"
              onClick={() => setEditing(!editing)}
            >
              Toggle Edit
            </Button>
          </CardActions>
        </Card>
      </CombinedDataProvider>
    </Container>
  );
}

(Source: components/profile/index.tsx)

Additional Information

You can view the source on GitHub.